Skip to content

Conversation

@knst
Copy link
Collaborator

@knst knst commented Nov 3, 2025

This PR is not meant to get merged, it's a proof-of-concept and consider it as a draft, see #What was done

Issue being fixed or feature implemented

Project of separation of consensus & chain code and network & node is blocked by tight connection of network and consensus code; in components such as llmq::CSigningManager, llmq::CSigSharesManager, coinjoin::client, coinjoin::server, governance, llmq::CInstantSendManager, etc.

What was done?

This PR is not meant to get merged as it is. Currently, it's a proof-of-concept that this approach is legit and could work for complex modules such as llmq::CSigSharesManager and CInstantSendManager.

Once it is done, it will unlock all backports related to kernel project, such as:

Prior approarches with using tl::expected (#5782 and other PRs), std::optional (such as #6282), MessageProcessingResult (#6292) helped to refactor code and prepare, reduced some dependencies, but they are not sufficient enough to provide reliable solution that works for complex non-trivial usages of PeerManager and network code all over codebase.

New approach introduces NetHandler which is a bridge interface between node/network related code and between consensus/chain code. In case if there is no need any network, objects that inherited by NetHandler are not created.

class NetHandler
{
public:
    NetHandler(PeerManagerInternal* peer_manager) : m_peer_manager{Assert(peer_manager)} {}
    virtual ~NetHandler() {
        Interrupt();
        Stop();
    }

    virtual void Start() {}
    virtual void Stop() {}
    virtual void Interrupt() {}
    virtual void Schedule(CScheduler& scheduler, CConnman& connman) {}
    virtual void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) {}
protected:
    PeerManagerInternal* m_peer_manager;
};

As a positive side-effect, amount of circular dependencies over net_processing is drastically reduced (56 of them to just 37).

How Has This Been Tested?

Run unit & functional tests.
Use linter test/lint-lint-circular-dependencies.py

Expected some thread safety analysis to fail, maybe some linters won't be happy.

Breaking Changes

N/A

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

knst added 30 commits October 27, 2025 04:03
…endency of msg_result on the heavy header

It's temporary refactoring; may be discarded later
…drop dependency of msg_result on the heavy header"

This reverts commit e38ffdc.
@knst knst added this to the 23.1 milestone Nov 3, 2025
@github-actions
Copy link

github-actions bot commented Nov 3, 2025

This pull request has conflicts, please rebase.

@knst
Copy link
Collaborator Author

knst commented Nov 3, 2025

@PastaPastaPasta @UdjinM6 @kwvg

Please give a look to this PR; I am looking for a concept review; any ideas & improvements on architecture level is welcome; thought any nits, typos, minor improvements will be considered by not expected yet.

If there's no objections or no major improvements, I am going to start from next week create smaller PRs which is merge-friendly (smaller scope to review; done self-review, all linters are happy, changes are atomic and separate).

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

This PR introduces a significant architectural refactoring to decouple consensus/chain code from network/node code by introducing the NetHandler interface pattern. The changes successfully move network message processing logic from net_processing.cpp into specialized handlers (NetInstantSend, NetSigning, NetGovernance), reducing circular dependencies from 56 to 37.

Key improvements:

  • New NetHandler base class provides lifecycle management (Start/Stop/Interrupt/Schedule)
  • PeerManagerInternal interface allows handlers to interact with peer management without direct coupling
  • MessageProcessingResult struct replaces direct PeerManager calls in consensus code
  • Network-specific code separated from consensus logic in signing, InstantSend, and governance modules
  • Governance sync moved from masternode/sync.cpp to new net_governance.cpp

Architecture changes:

  • Handlers registered via PeerManager::AddExtraHandler() during initialization
  • Message processing loop delegates to handlers sequentially
  • Each handler manages its own worker threads and scheduling
  • Shutdown sequence properly interrupts and stops handlers before cleanup

Confidence Score: 3/5

  • Architectural refactoring is sound but marked as draft/PoC with known threading concerns
  • The PR achieves its stated goal of decoupling consensus from networking code and significantly reduces circular dependencies. However, several factors warrant careful review: (1) PR is marked as draft/proof-of-concept by author, (2) author expects thread safety analysis to fail, (3) commented-out destructor code suggests uncertainty about lifecycle management, (4) duplicate thread names in NetSigning hamper debugging, (5) large refactoring touching 55 files with complex threading logic needs extensive testing
  • Focus testing on src/net_processing.cpp, src/net_signing.cpp, and src/init.cpp for proper handler lifecycle and thread safety. Verify shutdown sequence under various conditions.

Important Files Changed

File Analysis

Filename Score Overview
src/net_processing.cpp 3/5 Implemented handler management (Add/Remove/Start/Stop/Schedule) and PeerManagerInternal delegation methods. Destructor contains commented-out code. Message processing now delegates to handlers in loop.
src/net_instantsend.cpp 4/5 Implements ISDLOCK message processing with batch BLS signature verification. Thread lifecycle properly managed with interrupt mechanism. Moved from instantsend/instantsend.cpp.
src/net_signing.cpp 3/5 Implements recovered signature and sig share processing with batch verification. Two worker threads share same thread name "recsigs". Thread lifecycle uses assertions for validation.
src/net_governance.cpp 4/5 Moved governance sync logic from masternode/sync.cpp. Implements periodic governance object/vote requests and sync state management via scheduler.
src/init.cpp 4/5 Updated initialization sequence to register handlers after PeerManager creation. Shutdown sequence properly calls Interrupt/Remove/Stop handlers. Handler order matters for dependencies.
src/llmq/signing_shares.cpp 3/5 Large refactoring removed network message processing code moved to net_signing.cpp. Simplified interface reduces circular dependencies.

Sequence Diagram

sequenceDiagram
    participant Init as init.cpp
    participant PM as PeerManager
    participant NH as NetHandler
    participant NIS as NetInstantSend
    participant NS as NetSigning
    participant NG as NetGovernance
    participant ISM as InstantSendManager
    participant SM as SigningManager
    participant GM as GovernanceManager

    Note over Init,GM: Initialization Phase
    Init->>PM: Create PeerManager
    Init->>PM: AddExtraHandler(NetInstantSend)
    PM->>NIS: Create with ISManager & QManager
    Init->>PM: AddExtraHandler(NetSigning)
    PM->>NS: Create with SigningManager & SharesManager
    Note over Init: Wait for govman.IsValid()
    Init->>PM: AddExtraHandler(NetGovernance)
    PM->>NG: Create with GovernanceManager

    Note over Init,GM: Start Phase
    Init->>PM: StartHandlers()
    PM->>NIS: Start()
    NIS->>NIS: Launch WorkThread
    PM->>NS: Start()
    NS->>NS: Launch signing_thread & shares_thread
    Init->>PM: ScheduleHandlers(scheduler)
    PM->>NG: Schedule(scheduler)
    NG->>NG: Register periodic tasks

    Note over Init,GM: Message Processing
    PM->>PM: ProcessMessage(peer, msg_type)
    loop For each handler
        PM->>NH: ProcessMessage(peer, msg_type)
        alt ISDLOCK message
            NH->>NIS: ProcessMessage()
            NIS->>ISM: EnqueueInstantSendLock()
        else QSIGREC/QSIGSHARE message
            NH->>NS: ProcessMessage()
            NS->>SM: ProcessRecoveredSig()
        end
    end

    Note over Init,GM: Shutdown Phase
    Init->>PM: InterruptHandlers()
    PM->>NIS: Interrupt()
    NIS->>NIS: Set workInterrupt
    PM->>NS: Interrupt()
    NS->>NS: Set workInterrupt
    Init->>PM: RemoveHandlers()
    PM->>NIS: Stop()
    NIS->>NIS: Join WorkThread
    PM->>NS: Stop()
    NS->>NS: Join signing_thread & shares_thread
    PM->>PM: Clear m_handlers
Loading

Additional Comments (1)

  1. src/net_signing.cpp, line 406-410 (link)

    style: both worker threads use identical thread name "recsigs", making debugging difficult

55 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +598 to +601
~PeerManagerImpl() {
// probably do some disassignment
// m_handlers.clear();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: commented-out code in destructor should be removed or uncommented

the NetHandler base class destructor already calls Interrupt() and Stop(), so handlers should be cleaned up automatically. Either remove this comment or clarify why explicit cleanup might be needed

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/net_processing.cpp
Line: 598:601

Comment:
**style:** commented-out code in destructor should be removed or uncommented

the `NetHandler` base class destructor already calls `Interrupt()` and `Stop()`, so handlers should be cleaned up automatically. Either remove this comment or clarify why explicit cleanup might be needed

How can I resolve this? If you propose a fix, please make it concise.

@coderabbitai
Copy link

coderabbitai bot commented Nov 3, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR performs a comprehensive refactoring of the node's synchronization, networking, and signing architecture. The primary changes include: (1) relocating and renaming the masternode sync system to the node layer with constants renamed from MASTERNODE_SYNC_* to NODE_SYNC_*; (2) introducing a NetHandler-based modular architecture for networking components (NetGovernance, NetInstantSend, NetSigning) integrated via PeerManager; (3) removing worker thread infrastructure from CInstantSendManager and CSigningManager, shifting to event-driven processing; (4) eliminating CQuorumManager parameters from multiple constructor signatures; (5) restructuring governance logic with new public accessors and updated sync messaging; and (6) refactoring AsyncSignIfMember to remove the CSigningManager parameter across multiple call sites.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

  • Governance system refactoring: src/governance/governance.cpp and .h contain significant logic changes to voting preparation, object lookups, and sync message constants
  • InstantSend architecture shift: src/instantsend/instantsend.cpp and .h remove worker threads and substantially change API surface (constructor, return types, lifecycle methods)
  • Signing manager simplification: src/llmq/signing.cpp and .h remove CChainState dependency, eliminate worker threads, and introduce new processing methods
  • Signature sharing refactor: src/llmq/signing_shares.cpp and .h consolidate message handlers, change return types to return recovered signatures, and update AsyncSignIfMember signature
  • New handler architecture: src/net_processing.cpp/h, src/net_governance.cpp/h, src/net_signing.cpp/h, src/net_instantsend.cpp/h introduce interdependent handler lifecycle management
  • Cross-subsystem interconnections: Changes to AsyncSignIfMember, governance accessors, and peer manager APIs affect multiple files; thread safety and integration points require careful verification
  • Sync system relocation: src/node/sync.cpp/h and widespread include path migrations from masternode/sync.h to node/sync.h

Possibly related PRs

Suggested reviewers

  • PastaPastaPasta
  • UdjinM6

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "refactor: drop dependency on net_processing for multiple consensus related objects" directly and specifically summarizes the main change in the changeset. The title accurately reflects the primary objective of the refactoring effort—decoupling consensus-related components from net_processing dependencies through the introduction of the NetHandler interface. The language is clear and specific, avoiding vague terms, and a developer scanning the history would immediately understand the core refactoring initiative.
Description check ✅ Passed The PR description clearly relates to the changeset by explaining the refactoring effort to decouple network/node code from consensus/chain code through the introduction of a NetHandler bridge interface.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/node/chainstate.cpp (1)

243-259: Address TODO before merging: handler reconnection is incomplete.

The TODO comment indicates that network handlers (NetGovernance, NetInstantSend, NetSigning) need to be reconnected after the LLMQContext is recreated. This is critical for the new NetHandler architecture to function correctly after chainstate resets or reindexing.

Since this is marked as a draft PR, would you like me to help design the handler reconnection logic? The handlers would need to be:

  1. Stored in a way that survives the LLMQContext reset
  2. Re-registered with the new PeerManager instance after line 258

For reference, the test setup code at src/test/util/setup_common.cpp:370-375 shows how these handlers are initially created.

src/net_processing.h (1)

9-16: Add util/check.h for Assert usage
NetHandler now calls Assert(peer_manager) in the header, but this file doesn't include <util/check.h>. That symbol won't be declared here, so the build breaks as soon as the header is consumed. Please add the missing include.

 #include <net.h>
 #include <validationinterface.h>
 #include <version.h>
+#include <util/check.h>
🧹 Nitpick comments (5)
src/governance/object.cpp (1)

12-13: OK to use <node/sync.h>; consider pruning if unused

If this file no longer needs CMasternodeSync or related symbols, you can drop <node/sync.h> to reduce compile-time coupling. Optional.

src/coinjoin/server.cpp (1)

11-11: Include update is fine; net_processing dependency remains for future refactoring.

This file still includes net_processing.h and uses PeerManager directly (member variable at line 39 in server.h, parameter at line 99). Given the PR objective to decouple consensus-like components from net_processing, consider migrating to the proposed NetHandler bridge in a follow-up.

src/test/util/setup_common.cpp (1)

370-375: Fix typo in commented-out code before uncommenting.

Line 374 has an inconsistency: node.peerman should be m_node.peerman to match the pattern used on line 373 and elsewhere in the file.

Apply this diff to fix the typo:

-    node.peerman->AddExtraHandler(std::make_unique<NetGovernance>(node.peerman.get(), *node.govman, *node.mn_sync, *node.netfulfilledman));
+    m_node.peerman->AddExtraHandler(std::make_unique<NetGovernance>(m_node.peerman.get(), *m_node.govman, *m_node.mn_sync, *m_node.netfulfilledman));
src/llmq/signing.h (1)

197-198: Line 197: Make Qman() const so read-only callers can use it.

Qman() returns a const reference but the method itself isn't const, which means code that only has a const CSigningManager& can't access the quorum manager. Adding the const qualifier keeps the new accessor usable in those read-only contexts without changing behavior.

src/llmq/signing.cpp (1)

496-500: Consider optimization: returning listeners by value.

The method returns a copy of the listeners vector. While thread-safe, this could be optimized if performance becomes a concern:

  • Consider returning const std::vector<CRecoveredSigsListener*>& with the lock held externally
  • Or use a callback pattern to avoid copying

For now, correctness is prioritized over performance, which is appropriate for this refactoring.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f7dad69 and d88afaa.

📒 Files selected for processing (55)
  • src/Makefile.am (4 hunks)
  • src/chainlock/chainlock.cpp (1 hunks)
  • src/chainlock/signing.cpp (2 hunks)
  • src/coinjoin/client.cpp (1 hunks)
  • src/coinjoin/coinjoin.cpp (1 hunks)
  • src/coinjoin/server.cpp (1 hunks)
  • src/dsnotificationinterface.cpp (1 hunks)
  • src/evo/mnauth.cpp (1 hunks)
  • src/governance/governance.cpp (15 hunks)
  • src/governance/governance.h (3 hunks)
  • src/governance/object.cpp (1 hunks)
  • src/governance/signing.cpp (1 hunks)
  • src/governance/vote.cpp (1 hunks)
  • src/init.cpp (7 hunks)
  • src/instantsend/instantsend.cpp (8 hunks)
  • src/instantsend/instantsend.h (5 hunks)
  • src/instantsend/signing.cpp (3 hunks)
  • src/llmq/context.cpp (1 hunks)
  • src/llmq/ehf_signals.cpp (2 hunks)
  • src/llmq/quorums.cpp (1 hunks)
  • src/llmq/signing.cpp (8 hunks)
  • src/llmq/signing.h (5 hunks)
  • src/llmq/signing_shares.cpp (25 hunks)
  • src/llmq/signing_shares.h (3 hunks)
  • src/masternode/active/context.cpp (1 hunks)
  • src/masternode/active/notificationinterface.cpp (0 hunks)
  • src/masternode/active/notificationinterface.h (0 hunks)
  • src/masternode/payments.cpp (1 hunks)
  • src/masternode/sync.cpp (0 hunks)
  • src/masternode/utils.cpp (1 hunks)
  • src/msg_result.h (0 hunks)
  • src/net.cpp (1 hunks)
  • src/net.h (1 hunks)
  • src/net_governance.cpp (1 hunks)
  • src/net_governance.h (1 hunks)
  • src/net_instantsend.cpp (1 hunks)
  • src/net_instantsend.h (1 hunks)
  • src/net_processing.cpp (7 hunks)
  • src/net_processing.h (2 hunks)
  • src/net_signing.cpp (1 hunks)
  • src/net_signing.h (1 hunks)
  • src/node/chainstate.cpp (2 hunks)
  • src/node/context.cpp (1 hunks)
  • src/node/interfaces.cpp (1 hunks)
  • src/node/sync.cpp (1 hunks)
  • src/node/sync.h (4 hunks)
  • src/rpc/governance.cpp (1 hunks)
  • src/rpc/mining.cpp (1 hunks)
  • src/rpc/node.cpp (1 hunks)
  • src/rpc/quorums.cpp (1 hunks)
  • src/test/util/net.h (1 hunks)
  • src/test/util/setup_common.cpp (3 hunks)
  • src/validation.h (0 hunks)
  • src/wallet/interfaces.cpp (1 hunks)
  • test/lint/lint-circular-dependencies.py (2 hunks)
💤 Files with no reviewable changes (5)
  • src/masternode/active/notificationinterface.h
  • src/msg_result.h
  • src/masternode/sync.cpp
  • src/validation.h
  • src/masternode/active/notificationinterface.cpp
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{cpp,h,cc,cxx,hpp}: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction

Files:

  • src/governance/signing.cpp
  • src/rpc/governance.cpp
  • src/coinjoin/server.cpp
  • src/node/interfaces.cpp
  • src/test/util/setup_common.cpp
  • src/coinjoin/client.cpp
  • src/coinjoin/coinjoin.cpp
  • src/wallet/interfaces.cpp
  • src/masternode/payments.cpp
  • src/chainlock/chainlock.cpp
  • src/evo/mnauth.cpp
  • src/instantsend/signing.cpp
  • src/rpc/quorums.cpp
  • src/chainlock/signing.cpp
  • src/masternode/utils.cpp
  • src/net.cpp
  • src/rpc/node.cpp
  • src/rpc/mining.cpp
  • src/governance/object.cpp
  • src/node/sync.h
  • src/llmq/context.cpp
  • src/net_instantsend.h
  • src/llmq/quorums.cpp
  • src/dsnotificationinterface.cpp
  • src/node/chainstate.cpp
  • src/llmq/ehf_signals.cpp
  • src/masternode/active/context.cpp
  • src/net_processing.h
  • src/init.cpp
  • src/net.h
  • src/llmq/signing.h
  • src/net_signing.h
  • src/net_governance.h
  • src/test/util/net.h
  • src/net_governance.cpp
  • src/net_signing.cpp
  • src/node/context.cpp
  • src/instantsend/instantsend.h
  • src/governance/vote.cpp
  • src/net_instantsend.cpp
  • src/llmq/signing_shares.h
  • src/governance/governance.cpp
  • src/governance/governance.h
  • src/instantsend/instantsend.cpp
  • src/node/sync.cpp
  • src/net_processing.cpp
  • src/llmq/signing.cpp
  • src/llmq/signing_shares.cpp
src/{test,wallet/test,qt/test}/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests for C++ code should be placed in src/test/, src/wallet/test/, or src/qt/test/ and use Boost::Test or Qt 5 for GUI tests

Files:

  • src/test/util/setup_common.cpp
  • src/test/util/net.h
src/{masternode,evo}/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

Masternode lists must use immutable data structures (Immer library) for thread safety

Files:

  • src/masternode/payments.cpp
  • src/evo/mnauth.cpp
  • src/masternode/utils.cpp
  • src/masternode/active/context.cpp
🧠 Learnings (21)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
📚 Learning: 2025-07-20T18:42:49.794Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T18:42:49.794Z
Learning: Applies to src/{masternode,evo}/**/*.{cpp,h,cc,cxx,hpp} : Masternode lists must use immutable data structures (Immer library) for thread safety

Applied to files:

  • src/governance/signing.cpp
  • src/rpc/governance.cpp
  • src/coinjoin/server.cpp
  • src/node/interfaces.cpp
  • src/test/util/setup_common.cpp
  • src/coinjoin/client.cpp
  • src/coinjoin/coinjoin.cpp
  • src/wallet/interfaces.cpp
  • src/chainlock/chainlock.cpp
  • src/evo/mnauth.cpp
  • src/instantsend/signing.cpp
  • src/chainlock/signing.cpp
  • src/masternode/utils.cpp
  • src/net.cpp
  • src/rpc/node.cpp
  • src/rpc/mining.cpp
  • src/governance/object.cpp
  • src/node/sync.h
  • src/llmq/quorums.cpp
  • src/Makefile.am
  • src/dsnotificationinterface.cpp
  • src/init.cpp
  • src/node/context.cpp
  • src/governance/vote.cpp
  • src/instantsend/instantsend.cpp
  • src/node/sync.cpp
📚 Learning: 2025-01-07T18:50:44.838Z
Learnt from: knst
Repo: dashpay/dash PR: 6511
File: src/evo/deterministicmns.cpp:1369-1373
Timestamp: 2025-01-07T18:50:44.838Z
Learning: The functions `MigrateDBIfNeeded` and `MigrateDBIfNeeded2` in `src/evo/deterministicmns.cpp` are temporary and will be removed in a future version. Refactoring suggestions for these functions should be avoided.

Applied to files:

  • src/governance/signing.cpp
  • src/llmq/quorums.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • src/test/util/setup_common.cpp
  • test/lint/lint-circular-dependencies.py
📚 Learning: 2025-07-20T18:42:49.794Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T18:42:49.794Z
Learning: Applies to src/{test,wallet/test,qt/test}/**/*.{cpp,h,cc,cxx,hpp} : Unit tests for C++ code should be placed in src/test/, src/wallet/test/, or src/qt/test/ and use Boost::Test or Qt 5 for GUI tests

Applied to files:

  • src/test/util/setup_common.cpp
📚 Learning: 2025-10-02T18:29:54.756Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6840
File: src/net_processing.cpp:2882-2886
Timestamp: 2025-10-02T18:29:54.756Z
Learning: Across net_processing.cpp, once LLMQContext (m_llmq_ctx) is asserted non-null, its subcomponents (e.g., isman, qdkgsman, quorum_block_processor) are treated as initialized and used without extra null checks.

Applied to files:

  • src/test/util/setup_common.cpp
  • src/evo/mnauth.cpp
  • src/rpc/quorums.cpp
  • src/llmq/context.cpp
  • src/node/chainstate.cpp
  • src/masternode/active/context.cpp
  • src/net.h
  • src/llmq/signing.h
  • src/net_signing.cpp
  • src/instantsend/instantsend.h
  • src/net_instantsend.cpp
  • src/llmq/signing_shares.h
  • src/net_processing.cpp
  • src/llmq/signing.cpp
  • src/llmq/signing_shares.cpp
📚 Learning: 2025-10-03T11:20:37.475Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6838
File: src/active/context.cpp:29-33
Timestamp: 2025-10-03T11:20:37.475Z
Learning: In Dash codebase, NodeContext (src/node/context.h) serves only as a container with trivial c/d-tors; member lifetime is explicitly managed via reset() calls in the shutdown sequence (src/init.cpp), not by declaration order. For example, active_ctx.reset() is called before DashChainstateSetupClose handles llmq_ctx teardown, ensuring proper destruction order regardless of declaration order in the struct.

Applied to files:

  • src/test/util/setup_common.cpp
  • src/node/chainstate.cpp
  • src/init.cpp
  • src/node/context.cpp
📚 Learning: 2025-07-20T18:42:49.794Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T18:42:49.794Z
Learning: Applies to src/evo/specialtx.h : Special transactions use payload extensions defined in src/evo/specialtx.h

Applied to files:

  • src/coinjoin/client.cpp
  • src/wallet/interfaces.cpp
  • src/llmq/ehf_signals.cpp
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/wallet/interfaces.cpp
📚 Learning: 2025-01-02T21:50:00.967Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6504
File: src/llmq/context.cpp:42-43
Timestamp: 2025-01-02T21:50:00.967Z
Learning: LLMQContext manages concurrency for the `CInstantSendManager`. Previously, this was handled globally; now it's handled as a class member in `LLMQContext`, but the concurrency control remains consistent.

Applied to files:

  • src/instantsend/signing.cpp
  • src/llmq/context.cpp
  • src/net_instantsend.h
  • src/masternode/active/context.cpp
  • src/instantsend/instantsend.h
  • src/net_instantsend.cpp
  • src/llmq/signing_shares.h
  • src/instantsend/instantsend.cpp
📚 Learning: 2025-07-15T14:53:04.819Z
Learnt from: knst
Repo: dashpay/dash PR: 6691
File: src/test/llmq_params_tests.cpp:148-151
Timestamp: 2025-07-15T14:53:04.819Z
Learning: In the Dash Core LLMQ implementation, signingActiveQuorumCount is never 0 in the actual parameters defined in params.h, making division by zero scenarios unrealistic in the max_cycles() function.

Applied to files:

  • src/rpc/quorums.cpp
  • src/llmq/signing.h
  • src/llmq/signing_shares.cpp
📚 Learning: 2025-07-23T09:30:34.631Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.h:5-6
Timestamp: 2025-07-23T09:30:34.631Z
Learning: Dash Core uses BITCOIN_ prefix for header guards as the standard convention, inherited from Bitcoin Core. Only a few BLS-specific files in src/bls/ use DASH_ prefix. The vast majority of files (385+) use BITCOIN_ prefix.

Applied to files:

  • src/node/sync.h
📚 Learning: 2024-12-29T17:43:41.755Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6504
File: src/llmq/quorums.cpp:224-224
Timestamp: 2024-12-29T17:43:41.755Z
Learning: The `CQuorumManager` is fully initialized by `LLMQContext`, addressing any concerns about the manager’s initialization sequence.

Applied to files:

  • src/llmq/context.cpp
  • src/llmq/signing_shares.h
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().

Applied to files:

  • src/net_instantsend.h
  • src/net_instantsend.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/node/chainstate.cpp
📚 Learning: 2025-10-02T18:29:54.756Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6840
File: src/net_processing.cpp:2882-2886
Timestamp: 2025-10-02T18:29:54.756Z
Learning: In src/net_processing.cpp, if ActiveContext (m_active_ctx) is non-null, its members (including cj_server) are guaranteed to be initialized; call sites can safely dereference m_active_ctx->cj_server without an additional null-check.

Applied to files:

  • src/masternode/active/context.cpp
  • src/net_processing.cpp
📚 Learning: 2025-10-28T08:54:00.392Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6926
File: test/functional/feature_governance_cl.py:0-0
Timestamp: 2025-10-28T08:54:00.392Z
Learning: In Dash tests, the scheduler (mockscheduler) operates independently of network state. Isolated nodes should still run scheduler-based cleanup processes like governance cleanup, even if they have different state due to network isolation.

Applied to files:

  • src/init.cpp
  • src/governance/governance.cpp
📚 Learning: 2025-07-29T14:32:48.369Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.

Applied to files:

  • src/llmq/signing.h
  • src/llmq/signing.cpp
📚 Learning: 2025-08-19T15:08:00.835Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/commitment.cpp:54-60
Timestamp: 2025-08-19T15:08:00.835Z
Learning: In Dash Core, llmq_params.size == 1 is used only for regtest environments, not on public networks, which significantly reduces the risk profile of code paths specific to single-member quorums.

Applied to files:

  • src/llmq/signing.h
📚 Learning: 2025-09-09T13:04:06.013Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/compat/compat.h:0-0
Timestamp: 2025-09-09T13:04:06.013Z
Learning: WSAEISCONN is only used within WIN32 conditional compilation blocks in the codebase, so it doesn't require errno mapping for non-Windows platforms in src/compat/compat.h.

Applied to files:

  • src/test/util/net.h
📚 Learning: 2025-10-21T11:09:34.688Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6849
File: src/governance/governance.cpp:1339-1343
Timestamp: 2025-10-21T11:09:34.688Z
Learning: In PR #6849, `cmapVoteToObject` was intentionally moved from `GovernanceStore` to `CGovernanceManager` as a memory-only variable and is NOT guarded by `cs_store`. It relies on `CacheMap`'s internal thread-safety instead.

Applied to files:

  • src/governance/governance.cpp
  • src/governance/governance.h
🧬 Code graph analysis (19)
src/node/sync.h (6)
src/node/sync.cpp (18)
  • BumpAssetLastTime (41-46)
  • BumpAssetLastTime (41-41)
  • GetAssetName (48-57)
  • GetAssetName (48-48)
  • GetSyncStatus (87-95)
  • GetSyncStatus (87-87)
  • Reset (22-39)
  • Reset (22-22)
  • SwitchToNextAsset (59-85)
  • SwitchToNextAsset (59-59)
  • ProcessMessage (97-110)
  • ProcessMessage (97-97)
  • AcceptedBlockHeader (112-120)
  • AcceptedBlockHeader (112-112)
  • NotifyHeaderTip (122-135)
  • NotifyHeaderTip (122-122)
  • UpdatedBlockTip (137-174)
  • UpdatedBlockTip (137-137)
src/governance/governance.cpp (4)
  • ProcessMessage (183-325)
  • ProcessMessage (183-184)
  • UpdatedBlockTip (1229-1251)
  • UpdatedBlockTip (1229-1229)
src/coinjoin/client.cpp (8)
  • ProcessMessage (41-140)
  • ProcessMessage (41-42)
  • ProcessMessage (142-163)
  • ProcessMessage (142-142)
  • ProcessMessage (178-224)
  • ProcessMessage (178-178)
  • UpdatedBlockTip (1812-1816)
  • UpdatedBlockTip (1812-1812)
src/coinjoin/server.cpp (2)
  • ProcessMessage (26-40)
  • ProcessMessage (26-26)
src/evo/mnauth.cpp (2)
  • ProcessMessage (52-174)
  • ProcessMessage (52-54)
src/dsnotificationinterface.cpp (6)
  • AcceptedBlockHeader (46-50)
  • AcceptedBlockHeader (46-46)
  • NotifyHeaderTip (52-55)
  • NotifyHeaderTip (52-52)
  • UpdatedBlockTip (65-85)
  • UpdatedBlockTip (65-65)
src/net_instantsend.h (2)
src/net_processing.h (1)
  • PeerManagerInternal (58-72)
src/net_instantsend.cpp (12)
  • ProcessMessage (17-60)
  • ProcessMessage (17-17)
  • Start (62-75)
  • Start (62-62)
  • Stop (77-91)
  • Stop (77-77)
  • WorkThreadMain (241-265)
  • WorkThreadMain (241-241)
  • ProcessPendingISLocks (214-239)
  • ProcessPendingISLocks (214-214)
  • ProcessPendingInstantSendLocks (93-211)
  • ProcessPendingInstantSendLocks (93-95)
src/net_processing.h (6)
src/net_processing.cpp (86)
  • PeerMisbehaving (6527-6530)
  • PeerMisbehaving (6527-6527)
  • pnode (637-637)
  • pnode (642-642)
  • pnode (652-652)
  • pnode (737-737)
  • pnode (781-781)
  • pnode (853-853)
  • pnode (855-855)
  • PeerIsBanned (6532-6535)
  • PeerIsBanned (6532-6532)
  • node_id (653-653)
  • node_id (748-748)
  • PeerEraseObjectRequest (6537-6540)
  • PeerEraseObjectRequest (6537-6537)
  • nodeid (627-627)
  • nodeid (630-630)
  • nodeid (643-643)
  • nodeid (654-654)
  • nodeid (660-660)
  • nodeid (677-677)
  • nodeid (679-679)
  • nodeid (717-718)
  • nodeid (728-728)
  • nodeid (860-860)
  • nodeid (862-862)
  • nodeid (1038-1038)
  • nodeid (1072-1072)
  • inv (631-631)
  • inv (632-632)
  • inv (655-655)
  • inv (656-656)
  • inv (657-657)
  • inv (669-669)
  • inv (675-675)
  • inv (963-963)
  • inv (2388-2388)
  • PeerRelayInv (6542-6545)
  • PeerRelayInv (6542-6542)
  • PeerRelayInvFiltered (6547-6550)
  • PeerRelayInvFiltered (6547-6547)
  • PeerRelayInvFiltered (6552-6555)
  • PeerRelayInvFiltered (6552-6552)
  • PeerRelayRecoveredSig (6572-6575)
  • PeerRelayRecoveredSig (6572-6572)
  • sig_hash (658-658)
  • PeerAskPeersForTransaction (6557-6560)
  • PeerAskPeersForTransaction (6557-6557)
  • txid (633-633)
  • txid (659-659)
  • txid (663-663)
  • txid (666-666)
  • PeerGetRequestedObjectCount (6562-6565)
  • PeerGetRequestedObjectCount (6562-6562)
  • PeerPostProcessMessage (6567-6570)
  • PeerPostProcessMessage (6567-6567)
  • ret (661-661)
  • ret (683-683)
  • scheduler (623-623)
  • scheduler (649-649)
  • scheduler (692-692)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • pfrom (617-617)
  • pfrom (638-639)
  • pfrom (751-753)
  • pfrom (762-762)
  • pfrom (770-770)
  • pfrom (773-773)
  • pfrom (775-775)
  • pfrom (777-777)
  • pfrom (873-873)
  • pfrom (1055-1055)
  • AddExtraHandler (1651-1658)
  • AddExtraHandler (1651-1651)
  • handler (644-644)
  • RemoveHandlers (1660-1665)
  • RemoveHandlers (1660-1660)
  • StartHandlers (1667-1672)
  • StartHandlers (1667-1667)
  • StopHandlers (1674-1682)
  • StopHandlers (1674-1674)
  • InterruptHandlers (1684-1689)
  • InterruptHandlers (1684-1684)
  • ScheduleHandlers (1691-1696)
  • ScheduleHandlers (1691-1691)
src/net_instantsend.cpp (7)
  • inv (186-186)
  • Stop (77-91)
  • Stop (77-77)
  • Start (62-75)
  • Start (62-62)
  • ProcessMessage (17-60)
  • ProcessMessage (17-17)
src/init.cpp (3)
  • Interrupt (230-256)
  • Interrupt (230-230)
  • handler (480-480)
src/net_signing.cpp (6)
  • Stop (156-169)
  • Stop (156-156)
  • Start (144-154)
  • Start (144-144)
  • ProcessMessage (53-142)
  • ProcessMessage (53-53)
src/net_governance.cpp (2)
  • Schedule (21-54)
  • Schedule (21-21)
src/coinjoin/walletman.cpp (3)
  • Schedule (68-75)
  • Schedule (68-68)
  • connman (33-33)
src/llmq/signing.h (5)
src/llmq/signhash.h (3)
  • llmq (17-52)
  • SignHash (24-46)
  • hash (64-73)
src/llmq/signing_shares.cpp (4)
  • CSigSharesManager (179-189)
  • CSigSharesManager (191-191)
  • Cleanup (1133-1253)
  • Cleanup (1133-1133)
src/llmq/signhash.cpp (1)
  • SignHash (14-22)
src/llmq/signing.cpp (17)
  • CSigningManager (328-332)
  • AlreadyHave (334-347)
  • AlreadyHave (334-334)
  • GetRecoveredSigForGetData (349-359)
  • GetRecoveredSigForGetData (349-349)
  • ProcessRecoveredSig (361-381)
  • ProcessRecoveredSig (361-361)
  • ProcessRecoveredSig (455-494)
  • ProcessRecoveredSig (455-455)
  • FetchPendingReconstructed (447-452)
  • FetchPendingReconstructed (447-447)
  • CollectPendingRecoveredSigsToVerify (383-445)
  • CollectPendingRecoveredSigsToVerify (383-386)
  • GetListeners (496-500)
  • GetListeners (496-496)
  • Cleanup (513-526)
  • Cleanup (513-513)
src/net_signing.cpp (2)
  • ProcessRecoveredSig (171-182)
  • ProcessRecoveredSig (171-171)
src/net_signing.h (4)
src/llmq/signing_shares.h (1)
  • llmq (35-485)
src/llmq/signing.h (1)
  • CSigningManager (157-230)
src/net_processing.h (3)
  • NetHandler (74-90)
  • NetHandler (78-81)
  • PeerManagerInternal (58-72)
src/net_signing.cpp (22)
  • ProcessMessage (53-142)
  • ProcessMessage (53-53)
  • NotifyRecoveredSig (390-393)
  • NotifyRecoveredSig (390-390)
  • Start (144-154)
  • Start (144-144)
  • Stop (156-169)
  • Stop (156-156)
  • WorkThreadSigning (247-259)
  • WorkThreadSigning (247-247)
  • WorkThreadShares (355-388)
  • WorkThreadShares (355-355)
  • ProcessPendingSigShares (275-353)
  • ProcessPendingSigShares (275-275)
  • ProcessPendingRecoveredSigs (184-245)
  • ProcessPendingRecoveredSigs (184-184)
  • ProcessRecoveredSig (171-182)
  • ProcessRecoveredSig (171-171)
  • BanNode (41-51)
  • BanNode (41-41)
  • RemoveBannedNodeStates (261-271)
  • RemoveBannedNodeStates (261-261)
src/net_governance.h (4)
src/governance/governance.cpp (2)
  • CGovernanceManager (70-86)
  • CGovernanceManager (88-92)
src/node/sync.cpp (1)
  • CMasternodeSync (14-20)
src/net_processing.h (3)
  • NetHandler (74-90)
  • NetHandler (78-81)
  • PeerManagerInternal (58-72)
src/net_governance.cpp (8)
  • Schedule (21-54)
  • Schedule (21-21)
  • ProcessTick (143-323)
  • ProcessTick (143-143)
  • SendGovernanceSyncRequest (56-61)
  • SendGovernanceSyncRequest (56-56)
  • RequestGovernanceObjectVotes (63-141)
  • RequestGovernanceObjectVotes (63-63)
src/test/util/net.h (1)
src/net_processing.h (1)
  • PeerManager (105-105)
src/net_governance.cpp (2)
src/net_processing.cpp (9)
  • inv (631-631)
  • inv (632-632)
  • inv (655-655)
  • inv (656-656)
  • inv (657-657)
  • inv (669-669)
  • inv (675-675)
  • inv (963-963)
  • inv (2388-2388)
src/net.h (1)
  • FullyConnectedOnly (1291-1291)
src/net_signing.cpp (4)
src/llmq/signing_shares.cpp (2)
  • CSigSharesManager (179-189)
  • CSigSharesManager (191-191)
src/llmq/signing.cpp (6)
  • IsQuorumActive (588-597)
  • IsQuorumActive (588-588)
  • ProcessRecoveredSig (361-381)
  • ProcessRecoveredSig (361-361)
  • ProcessRecoveredSig (455-494)
  • ProcessRecoveredSig (455-455)
src/net_processing.cpp (19)
  • id (701-701)
  • id (705-705)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • pfrom (617-617)
  • pfrom (638-639)
  • pfrom (751-753)
  • pfrom (762-762)
  • pfrom (770-770)
  • pfrom (773-773)
  • pfrom (775-775)
  • pfrom (777-777)
  • pfrom (873-873)
  • pfrom (1055-1055)
  • WITH_LOCK (331-334)
  • WITH_LOCK (3234-3234)
  • WITH_LOCK (3256-3256)
  • now (689-689)
  • now (1012-1013)
src/net_signing.h (1)
  • Start (34-36)
src/instantsend/instantsend.h (3)
src/net_instantsend.h (1)
  • instantsend (12-16)
src/instantsend/lock.h (1)
  • instantsend (18-41)
src/instantsend/instantsend.cpp (14)
  • CInstantSendManager (51-62)
  • CInstantSendManager (64-64)
  • GetCycleBlockHeight (71-78)
  • GetCycleBlockHeight (71-71)
  • IsKnownInstantSend (80-87)
  • IsKnownInstantSend (80-80)
  • EnqueueInstantSendLock (89-110)
  • EnqueueInstantSendLock (89-89)
  • PrepareTxToRetry (391-407)
  • PrepareTxToRetry (391-391)
  • GetPendingLocks (112-143)
  • GetPendingLocks (112-112)
  • ProcessInstantSendLock (145-219)
  • ProcessInstantSendLock (145-146)
src/net_instantsend.cpp (1)
src/net_processing.cpp (25)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • pfrom (617-617)
  • pfrom (638-639)
  • pfrom (751-753)
  • pfrom (762-762)
  • pfrom (770-770)
  • pfrom (773-773)
  • pfrom (775-775)
  • pfrom (777-777)
  • pfrom (873-873)
  • pfrom (1055-1055)
  • id (701-701)
  • id (705-705)
  • ret (661-661)
  • ret (683-683)
  • inv (631-631)
  • inv (632-632)
  • inv (655-655)
  • inv (656-656)
  • inv (657-657)
  • inv (669-669)
  • inv (675-675)
  • inv (963-963)
  • inv (2388-2388)
src/llmq/signing_shares.h (4)
src/llmq/signing.h (2)
  • CRecoveredSigsListener (149-155)
  • nodiscard (69-91)
src/llmq/signing_shares.cpp (34)
  • CSigSharesManager (179-189)
  • CSigSharesManager (191-191)
  • CreateSigShare (1348-1416)
  • CreateSigShare (1348-1348)
  • ForceReAnnouncement (1419-1443)
  • ForceReAnnouncement (1419-1419)
  • HandleNewRecoveredSig (1445-1450)
  • HandleNewRecoveredSig (1445-1445)
  • AsyncSignIfMember (642-722)
  • AsyncSignIfMember (642-644)
  • FetchPendingSigShares (1319-1324)
  • FetchPendingSigShares (1319-1319)
  • SignPendingSigShare (1326-1346)
  • SignPendingSigShare (1326-1326)
  • SendMessages (973-1000)
  • SendMessages (973-973)
  • Cleanup (1133-1253)
  • Cleanup (1133-1133)
  • MarkAsBanned (1299-1317)
  • MarkAsBanned (1299-1299)
  • RemoveAsBanned (1282-1297)
  • RemoveAsBanned (1282-1282)
  • GetAllNodes (1270-1280)
  • GetAllNodes (1270-1270)
  • ProcessMessageSigShare (334-379)
  • ProcessMessageSigShare (334-334)
  • ProcessSigShare (495-546)
  • ProcessSigShare (495-495)
  • ProcessMessageSigSesAnn (203-233)
  • ProcessMessageSigSesAnn (203-203)
  • ProcessMessageSigShares (235-278)
  • ProcessMessageSigShares (235-235)
  • ProcessMessageBatchedSigShares (280-332)
  • ProcessMessageBatchedSigShares (280-280)
src/net_signing.cpp (2)
  • ProcessMessage (53-142)
  • ProcessMessage (53-53)
src/llmq/signhash.h (1)
  • llmq (17-52)
src/governance/governance.cpp (2)
src/node/interfaces.cpp (8)
  • hash (853-870)
  • hash (853-853)
  • hash (892-896)
  • hash (892-892)
  • hash (918-923)
  • hash (918-918)
  • vote (149-161)
  • vote (149-149)
src/governance/vote.cpp (1)
  • CGovernanceVote (84-93)
src/governance/governance.h (2)
src/governance/governance.cpp (14)
  • PrepareVotesToRequest (1056-1096)
  • PrepareVotesToRequest (1056-1056)
  • RequestOrphanObjects (1253-1278)
  • RequestOrphanObjects (1253-1253)
  • CleanOrphanObjects (1280-1296)
  • CleanOrphanObjects (1280-1280)
  • CheckAndRemove (415-534)
  • CheckAndRemove (415-415)
  • GetMNManager (536-539)
  • GetMNManager (536-536)
  • FetchRelayInventory (541-547)
  • FetchRelayInventory (541-541)
  • RequestGovernanceObject (1020-1049)
  • RequestGovernanceObject (1020-1020)
src/protocol.h (1)
  • CInv (531-568)
src/instantsend/instantsend.cpp (3)
src/logging.h (1)
  • LogAcceptDebug (235-238)
src/rpc/quorums.cpp (7)
  • WITH_LOCK (138-138)
  • WITH_LOCK (993-993)
  • ret (77-77)
  • ret (143-143)
  • ret (185-185)
  • ret (808-808)
  • ret (990-990)
src/node/interfaces.cpp (12)
  • hash (853-870)
  • hash (853-853)
  • hash (892-896)
  • hash (892-892)
  • hash (918-923)
  • hash (918-918)
  • LOCK (541-545)
  • LOCK (551-558)
  • LOCK (559-566)
  • LOCK (828-837)
  • LOCK (871-875)
  • LOCK (1055-1059)
src/node/sync.cpp (3)
src/net.h (1)
  • AllNodes (1297-1297)
src/net_processing.cpp (11)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • peer (697-697)
  • peer (832-832)
  • peer (937-937)
  • peer (938-938)
  • peer (1045-1045)
  • peer (1053-1053)
  • pindexNew (608-608)
  • UpdatedBlockTip (2192-2227)
  • UpdatedBlockTip (2192-2192)
src/dsnotificationinterface.cpp (6)
  • AcceptedBlockHeader (46-50)
  • AcceptedBlockHeader (46-46)
  • NotifyHeaderTip (52-55)
  • NotifyHeaderTip (52-52)
  • UpdatedBlockTip (65-85)
  • UpdatedBlockTip (65-65)
src/net_processing.cpp (3)
src/wallet/interfaces.cpp (2)
  • scheduler (624-624)
  • scheduler (624-624)
src/validationinterface.cpp (4)
  • RegisterValidationInterface (133-138)
  • RegisterValidationInterface (133-133)
  • UnregisterValidationInterface (145-150)
  • UnregisterValidationInterface (145-145)
src/llmq/dkgsessionhandler.cpp (2)
  • Misbehaving (112-116)
  • Misbehaving (112-112)
src/llmq/signing.cpp (2)
src/llmq/signing.h (1)
  • CSigningManager (157-230)
src/net_signing.cpp (2)
  • ProcessRecoveredSig (171-182)
  • ProcessRecoveredSig (171-171)
src/llmq/signing_shares.cpp (3)
src/net_processing.cpp (14)
  • node_id (653-653)
  • node_id (748-748)
  • LOCK (323-329)
  • LOCK (336-340)
  • LOCK (341-345)
  • id (701-701)
  • id (705-705)
  • pnode (637-637)
  • pnode (642-642)
  • pnode (652-652)
  • pnode (737-737)
  • pnode (781-781)
  • pnode (853-853)
  • pnode (855-855)
src/spork.h (1)
  • cs (226-339)
src/llmq/signing.cpp (2)
  • IsQuorumActive (588-597)
  • IsQuorumActive (588-588)
🪛 GitHub Actions: Check Merge Fast-Forward Only
src/governance/governance.cpp

[error] 1-1: Automatic merge failed due to merge conflicts in governance.cpp. Resolve conflicts and commit the result.

src/governance/governance.h

[error] 1-1: Automatic merge failed due to merge conflicts in governance.h. Resolve conflicts and commit the result.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (53)
src/net.h (1)

38-38: Header dependency swap verified as safe.

The change replaces #include <consensus/params.h> with #include <llmq/params.h>. Verification confirms that all symbols used by net.h—specifically Consensus::LLMQType—are properly defined in llmq/params.h. The refactoring correctly decouples network code from generic consensus parameters while maintaining all necessary functionality. No missing symbols or breakage detected.

src/test/util/net.h (1)

27-27: LGTM! Proper use of forward declaration to reduce header dependencies.

The forward declaration is appropriate since PeerManager is only used by reference (line 80) in this header. This eliminates the need to include net_processing.h, reducing compilation dependencies and supporting the PR's goal of decoupling network/node code from consensus/chain code.

src/Makefile.am (1)

298-300: LGTM - New NetHandler headers added.

The addition of net_governance.h, net_instantsend.h, and net_signing.h to the public headers aligns with the PR's objective of introducing NetHandler bridge interfaces.

src/llmq/signing_shares.h (5)

360-366: LGTM - Well-designed public struct.

The PendingSignatureData struct is cleanly designed with const members ensuring immutability. This promotes the previously internal concept to the public API to support NetSigning integration.


389-389: Verify necessity of RecursiveMutex change.

The mutex type changed from Mutex to RecursiveMutex. While this enables re-entrant locking, recursive mutexes can indicate unclear lock hierarchies and are generally discouraged in favor of explicit lock ordering.

Please verify:

  1. Whether the recursive locking is truly necessary for the NetSigning refactor
  2. If the call graph can be restructured to use a standard Mutex with clear lock ordering
  3. That no deadlock scenarios are introduced by the new locking patterns

If recursive locking is required for this refactor, consider documenting the specific call paths that necessitate it.


443-461: LGTM - Public API expansion for NetSigning integration.

The expanded public surface with methods like FetchPendingSigShares(), SignPendingSigShare(), SendMessages(), and Cleanup() aligns with the PR's objective of introducing the NetHandler bridge architecture. These methods enable NetSigning to coordinate signature share management without tight coupling.


437-440: All call sites correctly updated.

Verification complete. All 5 call sites across the codebase (chainlock/signing.cpp, llmq/ehf_signals.cpp, rpc/quorums.cpp, and instantsend/signing.cpp) correctly use the new AsyncSignIfMember signature. Parameters are passed in the correct order, required arguments are provided, and optional parameters are either explicitly passed or use the defaults as intended. No instances of the old signature with CSigningManager& parameter were found.


470-470: No issues found - all call sites handle the new return type correctly.

The comprehensive search confirms TryRecoverSig appears only in src/llmq/signing_shares.h (declaration) and src/llmq/signing_shares.cpp (implementation and single call site). The one call site at line 543 correctly forwards the return value to its caller, which properly handles the std::shared_ptr<CRecoveredSig> return type. The API change has been correctly implemented throughout the codebase.

src/chainlock/chainlock.cpp (1)

21-21: LGTM - Header path updated correctly.

The include path change from masternode/sync.h to node/sync.h is consistent with the PR's objective of moving synchronization functionality to the node layer.

src/rpc/mining.cpp (1)

49-49: LGTM - Header path updated correctly.

The include path change from masternode/sync.h to node/sync.h is consistent with the broader refactoring effort to relocate synchronization to the node layer.

src/dsnotificationinterface.cpp (1)

21-21: LGTM - Header path updated correctly.

The include path change from masternode/sync.h to node/sync.h aligns with the PR's synchronization layer refactoring.

src/rpc/governance.cpp (1)

15-15: Include updated to <node/sync.h>

Matches the NodeContext usage (node.mn_sync). No further changes needed here.

src/coinjoin/coinjoin.cpp (1)

19-19: Verification successful: no-arg invocation supported

The IsTimeOutOfBounds() method in CCoinJoinQueue (src/coinjoin/coinjoin.h:215) accepts an optional parameter with a default value: int64_t current_time = GetAdjustedTime(). This allows the method to be invoked without arguments, confirming the code change is sound and properly layered.

src/net.cpp (1)

44-44: Header swap verified and correct

The change is valid. node/sync.h provides the CMasternodeSync class (defined at line 35) that net.cpp uses across 8+ functions as parameters. All usages remain compatible, the old header is cleanly removed from the codebase, and the new header is consistently adopted across all 28 dependent files. No compilation issues expected.

src/masternode/utils.cpp (1)

13-13: Include path update acknowledged.

No issues spotted; ensure build bots cover platforms where header search order differed.

src/chainlock/signing.cpp (2)

13-13: Switched to node/sync.h.

Looks consistent with the repo-wide move.


144-144: All AsyncSignIfMember call sites are correctly aligned with the updated signature.

The verification confirms:

  • Function signature accepts 3 required parameters (llmqType, id, msgHash) plus 3 optional parameters with defaults
  • The 3-argument call at src/chainlock/signing.cpp:144 is valid and uses defaults for optional parameters
  • All five call sites across the codebase correctly use the updated signature
  • No stray old-style calls remain
src/masternode/payments.cpp (1)

15-15: Include path update OK.

No functional impact observed.

src/coinjoin/client.cpp (1)

13-13: Header move confirmed.

CoinJoin client still compiles against CMasternodeSync semantics via node/sync.h? Please confirm with the verification script posted on quorums.cpp.

src/evo/mnauth.cpp (1)

13-13: Include switch LGTM.

No other diffs in MNAUTH flow.

src/wallet/interfaces.cpp (1)

35-35: Header move acknowledged.

Wallet interfaces unaffected; safe.

src/llmq/quorums.cpp (1)

21-21: Header migration verified complete and clean.

Verification confirms no lingering includes of masternode/sync.h or stale MASTERNODE_SYNC_* constants remain in the codebase. The CMasternodeSync class is properly declared and defined in src/node/sync.h. The include change at Line 21 is correct.

src/governance/signing.cpp (1)

10-10: LGTM! Include path updated for node-layer sync.

The include path change from masternode/sync.h to node/sync.h aligns with the PR's objective to relocate synchronization functionality to the node layer.

src/node/context.cpp (1)

23-23: LGTM! Include path updated for node-layer sync.

The include path change from masternode/sync.h to node/sync.h aligns with the PR's objective to relocate synchronization functionality to the node layer.

src/rpc/node.cpp (1)

35-35: LGTM! Include path updated for node-layer sync.

The include path change from masternode/sync.h to node/sync.h aligns with the PR's objective to relocate synchronization functionality to the node layer.

src/governance/vote.cpp (1)

10-10: LGTM! Include path updated for node-layer sync.

The include path change from masternode/sync.h to node/sync.h aligns with the PR's objective to relocate synchronization functionality to the node layer.

src/node/interfaces.cpp (1)

28-28: LGTM! Include path updated for node-layer sync.

The include path change from masternode/sync.h to node/sync.h aligns with the PR's objective to relocate synchronization functionality to the node layer.

src/test/util/setup_common.cpp (1)

20-24: LGTM! New includes added for NetHandler architecture.

The new includes for masternode/active/context.h, net_instantsend.h, and net_signing.h support the NetHandler-based networking components. The update from masternode/sync.h to node/sync.h aligns with the PR's sync relocation objectives.

Also applies to: 70-70

src/net_governance.h (1)

1-35: LGTM! Well-designed NetHandler for governance networking.

The NetGovernance class follows the NetHandler pattern consistently:

  • Properly derives from NetHandler and forwards PeerManagerInternal* to the base
  • Stores governance dependencies as references (appropriate since ownership is external)
  • Marked as final to prevent unintended inheritance
  • Implements the Schedule() hook for periodic governance sync tasks

The interface is clean and the responsibilities are well-defined.

src/instantsend/instantsend.h (5)

125-138: LGTM! Clean bridge interface for NetInstantSend integration.

The new public methods provide a well-structured interface for communication between CInstantSendManager and NetInstantSend. The return types are appropriate:

  • GetCycleBlockHeight returns negative for unknown cycle_hash (documented)
  • ProcessInstantSendLock uses std::variant for flexible return values
  • Accessors (Sigman(), Chainstate()) provide controlled access to dependencies

100-100: LGTM! Accessor provides safe access to signer.

The Signer() accessor correctly returns the atomic-loaded pointer, allowing external components to access the signer when needed. Callers should handle the potential nullptr return value appropriately.


8-10: LGTM! Include additions support new functionality.

The added includes are necessary for:

  • <variant>: Return type of ProcessInstantSendLock
  • <instantsend/db.h>, <instantsend/lock.h>, <instantsend/signing.h>: Support new data structures and types used in the interface

Also applies to: 22-23


38-41: PendingState data structure change verified successfully.

The PendingState.m_pending_is member type has been properly updated to Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>> and all code that accesses this structure is compatible with the new type.

Verification confirms:

  • Old member m_pending_peer_activity is completely removed
  • All operations on m_pending_is use standard std::unordered_map methods (size(), emplace(), find(), erase())
  • The single call site in net_instantsend.cpp:247 correctly unpacks the structure via structured binding and passes the result to ProcessPendingISLocks() with matching type and move semantics
  • Consumer code properly handles the new type throughout

87-89: Constructor call sites are already correctly updated.

The single instantiation in src/llmq/context.cpp:35-36 correctly passes all 8 arguments matching the current constructor signature. No CQuorumManager parameter exists in either the signature or call site, confirming the refactoring was completed as intended.

Likely an incorrect or invalid review comment.

src/llmq/signing.cpp (4)

447-452: LGTM! Efficient extraction of pending reconstructed signatures.

The FetchPendingReconstructed method uses swap to efficiently extract pending signatures while holding the lock. This is a clean pattern for moving data out of a protected container.


418-418: LGTM! Structured bindings improve readability.

The use of C++17 structured bindings (auto& [nodeId, v]) is cleaner and more readable than traditional iterator access patterns. This is appropriate for a C++20 codebase.


361-381: LGTM! Call sites correctly handle new return types.

Verified that all ProcessRecoveredSig invocations properly match their return types:

  • Line 67 (NodeId overload): Return value correctly discarded (void)
  • Line 173 (const overload): Return value correctly checked as bool

The changes are consistent throughout and no fixes are needed.


328-332: Constructor signature change verified and all call sites updated correctly.

The CSigningManager constructor signature has been successfully updated to remove the CChainState& parameter. Verification confirms that the only instantiation site in src/llmq/context.cpp:33 correctly passes three arguments matching the new signature: std::make_unique<llmq::CSigningManager>(*qman, unit_tests, wipe), which corresponds to the three parameters (const CQuorumManager& _qman, bool fMemory, bool fWipe).

No issues found.

src/instantsend/instantsend.cpp (6)

71-78: LGTM! Thread-safe implementation with proper error handling.

The GetCycleBlockHeight method correctly:

  • Uses WITH_LOCK(::cs_main, ...) for thread-safe access to m_blockman
  • Returns -1 for unknown cycle hashes (documented in header)
  • Handles the nullptr case safely

80-87: LGTM! Comprehensive check for known InstantSend locks.

The method correctly checks both pending locks (with proper synchronization) and the database. The implementation is straightforward and thread-safe.


112-143: LGTM! Efficient batching with proper synchronization.

The implementation correctly:

  • Limits batch size to 32 items to avoid overwhelming parallel verification (as noted in comment)
  • Uses std::move to transfer ownership efficiently
  • Sets m_pending_work flag when more items remain
  • Removes processed items after iteration to avoid iterator invalidation

391-407: LGTM! Clean extraction of pending transactions.

The method correctly:

  • Acquires both locks in a consistent order (LOCK2)
  • Returns early if no pending transactions
  • Uses structured bindings for clarity
  • Only includes transactions with valid tx_info.tx

66-69: LGTM! Clean extraction of timing reporting logic.

The free function ShouldReportISLockTiming() consolidates the logic for determining when to report timing metrics. This improves code readability and reduces duplication.


145-219: LGTM! Improved return semantics using std::variant.

The new return type std::variant<uint256, CTransactionRef, std::monostate> provides clearer semantics and all call sites properly handle the three cases:

  • std::monostate: Lock already known or can be ignored (handled via assert)
  • uint256: Transaction ID when TX not found yet—triggers peer lookup for the missing transaction
  • CTransactionRef: Full transaction when lock successfully processed—relayed to peers

The call site in src/net_instantsend.cpp:187 correctly uses std::holds_alternative to dispatch on each variant type, ensuring complete coverage of all three return states.

src/llmq/signing_shares.cpp (9)

203-233: LGTM! Clean transition to NodeId-based processing.

The method signature change from peer reference to NodeId node_id successfully decouples from PeerManager. The NodeId is used consistently throughout for logging and state access.


548-625: LGTM! Consistent return type with clear success/failure semantics.

The method returns nullptr for various failure conditions (quorum issues, insufficient shares, invalid signature) and std::shared_ptr<CRecoveredSig> on success. This is clear and consistent with ProcessSigShare.


642-722: LGTM! Clean async signing with proper synchronization.

The method correctly:

  • Validates quorum membership before signing
  • Checks for conflicting votes in the database
  • Uses LOCK(cs_pendingSigns) to safely add to pendingSigns
  • Returns bool to indicate success/failure

The locking pattern at lines 718-719 is correct for protecting the pendingSigns container.


1270-1280: LGTM! Simple accessor for node IDs.

The GetAllNodes method provides a thread-safe way to get all tracked node IDs. The implementation is straightforward and uses proper locking.


1282-1297: LGTM! Clean removal of banned node state.

The RemoveAsBanned method correctly:

  • Acquires the lock
  • Re-requests sig shares from other nodes (via ForEach callback)
  • Removes the node state entirely

This allows recovery after a node is unbanned.


1299-1317: LGTM! Proper handling of banned nodes.

The MarkAsBanned method:

  • Clears requested shares so they can be requested from other nodes
  • Sets the banned flag instead of removing state immediately
  • Allows later cleanup by Cleanup() method

This is cleaner than immediate removal and prevents resource leaks.


1319-1346: LGTM! Clean extraction and processing of pending signatures.

The new methods support event-driven processing:

  • FetchPendingSigShares efficiently extracts pending signatures using swap
  • SignPendingSigShare creates, processes, and returns recovered signatures
  • Proper synchronization with cs_pendingSigns and cs

These methods enable NetSigning to process signatures on-demand rather than in a dedicated worker thread.


495-546: Return type change properly implemented with correct null handling at all call sites.

Verification confirms:

  • net_signing.cpp:341: Explicitly checks if (rs != nullptr) before processing the recovered signature ✓
  • signing_shares.cpp:1333: Safely returns the result for caller to handle ✓

Both call sites correctly manage the std::shared_ptr<CRecoveredSig> return type and handle nullptr appropriately. The code change is sound.


179-188: Code is internally consistent; review comment appears based on unavailable AI summary context.

The actual constructor signature (lines 179-188) includes the CSigningManager& _sigman parameter and properly initializes it via sigman{_sigman} on line 184. The provided code snippet matches the actual file exactly. No inconsistency exists within the code itself. The review comment's concern references an "AI summary" claiming the parameter should have been removed, but without access to that summary or PR context, this cannot be verified. The code as written is self-consistent.

src/Makefile.am Outdated
node/miner.h \
node/minisketchwrapper.h \
node/psbt.h \
sync/sync.h \
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Incorrect header path - should be node/sync.h.

The header path sync/sync.h is inconsistent with the corresponding source file node/sync.cpp added at Line 577 and the include paths used in other files (#include <node/sync.h>).

Apply this diff:

-  sync/sync.h \
+  node/sync.h \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sync/sync.h \
node/sync.h \
🤖 Prompt for AI Agents
In src/Makefile.am around line 318, the listed header path "sync/sync.h" is
incorrect and must match the actual header location used by the source and
includes; update that entry to "node/sync.h" so the Makefile installs/refs the
correct header path and aligns with node/sync.cpp and other files that use
#include <node/sync.h>.

Comment on lines +21 to +54
void NetGovernance::Schedule(CScheduler& scheduler, CConnman& connman)
{
if (!m_gov_manager.IsValid()) return;

scheduler.scheduleEvery(
[this, &connman]() -> void {
if (ShutdownRequested()) return;
ProcessTick(connman);
},
std::chrono::seconds{1});

scheduler.scheduleEvery(
[this, &connman]() -> void {
if (!m_node_sync.IsSynced()) return;

// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
m_gov_manager.CleanOrphanObjects();
m_gov_manager.RequestOrphanObjects(connman);

// CHECK AND REMOVE - REPROCESS GOVERNANCE OBJECTS
m_gov_manager.CheckAndRemove();
},
std::chrono::minutes{5});

scheduler.scheduleEvery(
[this]() -> void {
auto relay_invs = m_gov_manager.FetchRelayInventory();
for (const auto& inv : relay_invs) {
m_peer_manager->PeerRelayInv(inv);
}
},
// Tests need tighter timings to avoid timeouts, use more relaxed pacing otherwise
Params().IsMockableChain() ? std::chrono::seconds{1} : std::chrono::seconds{5});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Don’t gate the tick loop on governance availability
Returning immediately when m_gov_manager is invalid prevents us from scheduling ProcessTick() at all. On nodes started with -disablegovernance (or otherwise lacking the DB), this leaves CMasternodeSync stuck in NODE_SYNC_BLOCKCHAIN forever—SwitchToNextAsset() is never reached, mempool sync never fires, and the node never reports itself as synced. Previously the tick ran regardless of governance state, so this is a regression with user-visible fallout. Please keep the 1 s ProcessTick() schedule active unconditionally and only skip the other two maintenance jobs when governance is actually available. A minimal fix would look like:

-    if (!m_gov_manager.IsValid()) return;
-
-    scheduler.scheduleEvery(
-            [this, &connman]() -> void {
-                if (ShutdownRequested()) return;
-                ProcessTick(connman);
-            },
-         std::chrono::seconds{1});
+    scheduler.scheduleEvery(
+        [this, &connman]() -> void {
+            if (ShutdownRequested()) return;
+            ProcessTick(connman);
+        },
+        std::chrono::seconds{1});
+
+    if (!m_gov_manager.IsValid()) return;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void NetGovernance::Schedule(CScheduler& scheduler, CConnman& connman)
{
if (!m_gov_manager.IsValid()) return;
scheduler.scheduleEvery(
[this, &connman]() -> void {
if (ShutdownRequested()) return;
ProcessTick(connman);
},
std::chrono::seconds{1});
scheduler.scheduleEvery(
[this, &connman]() -> void {
if (!m_node_sync.IsSynced()) return;
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
m_gov_manager.CleanOrphanObjects();
m_gov_manager.RequestOrphanObjects(connman);
// CHECK AND REMOVE - REPROCESS GOVERNANCE OBJECTS
m_gov_manager.CheckAndRemove();
},
std::chrono::minutes{5});
scheduler.scheduleEvery(
[this]() -> void {
auto relay_invs = m_gov_manager.FetchRelayInventory();
for (const auto& inv : relay_invs) {
m_peer_manager->PeerRelayInv(inv);
}
},
// Tests need tighter timings to avoid timeouts, use more relaxed pacing otherwise
Params().IsMockableChain() ? std::chrono::seconds{1} : std::chrono::seconds{5});
}
void NetGovernance::Schedule(CScheduler& scheduler, CConnman& connman)
{
scheduler.scheduleEvery(
[this, &connman]() -> void {
if (ShutdownRequested()) return;
ProcessTick(connman);
},
std::chrono::seconds{1});
if (!m_gov_manager.IsValid()) return;
scheduler.scheduleEvery(
[this, &connman]() -> void {
if (!m_node_sync.IsSynced()) return;
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
m_gov_manager.CleanOrphanObjects();
m_gov_manager.RequestOrphanObjects(connman);
// CHECK AND REMOVE - REPROCESS GOVERNANCE OBJECTS
m_gov_manager.CheckAndRemove();
},
std::chrono::minutes{5});
scheduler.scheduleEvery(
[this]() -> void {
auto relay_invs = m_gov_manager.FetchRelayInventory();
for (const auto& inv : relay_invs) {
m_peer_manager->PeerRelayInv(inv);
}
},
// Tests need tighter timings to avoid timeouts, use more relaxed pacing otherwise
Params().IsMockableChain() ? std::chrono::seconds{1} : std::chrono::seconds{5});
}
🤖 Prompt for AI Agents
In src/net_governance.cpp around lines 21 to 54, the current early return when
m_gov_manager.IsValid() is false prevents scheduling the 1s ProcessTick() job
and stalls node sync; change the logic so the 1-second scheduler for
ProcessTick(connman) is always registered unconditionally, and only gate the two
governance-related scheduled tasks (the 5-minute Clean/Request/Check task and
the relay inventory task) on m_gov_manager.IsValid(); remove the top-level
return and wrap the other two scheduler.scheduleEvery(...) calls in an if
(m_gov_manager.IsValid()) { ... } (or equivalent) so governance-dependent jobs
are skipped when invalid but ProcessTick still runs.

Comment on lines +167 to +174
nTimeLastProcess = GetTime();
const CConnman::NodesSnapshot snap{connman, /* cond = */ CConnman::FullyConnectedOnly};

// gradually request the rest of the votes after sync finished
if(m_node_sync.IsSynced()) {
RequestGovernanceObjectVotes(snap.Nodes(), connman);
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Skip vote requests when governance is disabled
Once the tick runs even without governance, this IsSynced() early return will still invoke RequestGovernanceObjectVotes, which dereferences the governance manager. On a node started with -disablegovernance, that’s undefined behaviour. Guarding this block fixes the issue:

-    if(m_node_sync.IsSynced()) {
+    if(!m_gov_manager.IsValid()) {
+        return;
+    }
+    if (m_node_sync.IsSynced()) {
         RequestGovernanceObjectVotes(snap.Nodes(), connman);
         return;
     }

This keeps the sync state machine advancing while cleanly bailing out of vote polling when governance is unavailable.

🤖 Prompt for AI Agents
In src/net_governance.cpp around lines 167 to 174, when the node is synced the
code unconditionally calls RequestGovernanceObjectVotes which dereferences the
governance manager and causes undefined behaviour when governance is disabled;
update the early-return block to first check whether governance is
enabled/available (e.g., guard with the governance manager presence or a
disable-governance flag) and only call RequestGovernanceObjectVotes if
governance is enabled, otherwise skip the vote-request call while still allowing
the sync state machine to advance.

Comment on lines +217 to +221
auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
assert(llmq_params_opt);
const auto& llmq_params = llmq_params_opt.value();
auto dkgInterval = llmq_params.dkgInterval;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Prevent crash when the DIP24 quorum is unavailable.
When llmqTypeDIP0024InstantSend is LLMQ_NONE (e.g., in regtest/unit-test setups or any network that has not configured a DIP24 quorum yet), Params().GetLLMQ(llmqType) returns std::nullopt. Calling .value() in either ProcessPendingISLocks or ProcessMessage will then throw std::bad_optional_access, terminating the node. Please guard the optional before dereferencing and bail out early if no quorum is configured.

     auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
-    const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
-    assert(llmq_params_opt);
-    const auto& llmq_params = llmq_params_opt.value();
+    const auto llmq_params_opt = Params().GetLLMQ(llmqType);
+    if (!llmq_params_opt.has_value()) {
+        return;
+    }
+    const auto& llmq_params = *llmq_params_opt;

(The same guard should be applied in ProcessMessage.)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
assert(llmq_params_opt);
const auto& llmq_params = llmq_params_opt.value();
auto dkgInterval = llmq_params.dkgInterval;
auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
const auto llmq_params_opt = Params().GetLLMQ(llmqType);
if (!llmq_params_opt.has_value()) {
return;
}
const auto& llmq_params = *llmq_params_opt;
auto dkgInterval = llmq_params.dkgInterval;
🤖 Prompt for AI Agents
In src/net_instantsend.cpp around lines 217 to 221, the code calls
llmq_params_opt.value() without checking the optional, which crashes when the
DIP24 quorum is not configured (std::bad_optional_access); update the code to
check the optional before dereferencing (e.g., if (!llmq_params_opt) return or
otherwise bail out/skip InstantSend processing when llmqTypeDIP0024InstantSend
is LLMQ_NONE or GetLLMQ returns nullopt), and apply the identical guard in
ProcessMessage to avoid accessing .value() when the quorum is unavailable.

Comment on lines +6567 to +6570
void PeerManagerImpl::PeerPostProcessMessage(MessageProcessingResult&& ret)
{
PostProcessMessage(std::move(ret), -1);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Incorrect peer id passed through PeerPostProcessMessage

PeerPostProcessMessage now forwards every result to PostProcessMessage with node = -1. That short-circuits key paths: Misbehaving(-1, …) bails out, so handlers can no longer raise bans, and EraseObjectRequest(-1, …) never clears g_already_asked_for, leaving stale getdata bookkeeping and blocking future retries. This regresses existing DoS protection and request accounting, so we must propagate the real peer id.

Please change the interface/implementation to pass the originating NodeId down (similar to the direct call sites above), for example:

-void PeerPostProcessMessage(MessageProcessingResult&& ret) override {
-    PostProcessMessage(std::move(ret), -1);
-}
+void PeerPostProcessMessage(NodeId nodeid, MessageProcessingResult&& ret) override {
+    PostProcessMessage(std::move(ret), nodeid);
+}

and adjust callers accordingly so handlers supply the true peer id.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/net_processing.cpp around lines 6567-6570, PeerPostProcessMessage
currently forwards results to PostProcessMessage with node = -1 which prevents
Misbehaving() and EraseObjectRequest() from operating on the real peer; update
the PeerPostProcessMessage signature and body to accept and pass the originating
NodeId through to PostProcessMessage (i.e. replace the hardcoded -1 with the
provided node id), then update all callers of PeerPostProcessMessage to supply
the true NodeId from their context so handlers can correctly record misbehavior
and clear g_already_asked_for.

Comment on lines +7 to +26
#include <bls/bls_batchverifier.h>
#include <cxxtimer.hpp>
#include <llmq/commitment.h>
#include <llmq/quorums.h>
#include <llmq/signhash.h>
#include <llmq/signing.h>
#include <llmq/signing_shares.h>
#include <masternode/node.h>
#include <logging.h>
#include <spork.h>
#include <streams.h>
#include <util/thread.h>
#include <validationinterface.h>

#include <unordered_map>

using llmq::CSigSharesManager;

static bool PreVerifyRecoveredSig(Consensus::LLMQType& llmqType, const llmq::CQuorumManager& quorum_manager, const llmq::CRecoveredSig& recoveredSig)
{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Include util/ranges.h before using ranges::all_of
This new file relies on the ranges::all_of alias, which Dash exposes via <util/ranges.h>. Without that header the compiler reports “namespace ‘ranges’ has not been declared”. Please pull in the helper before using the alias.

 #include <llmq/signing.h>
 #include <llmq/signing_shares.h>
 #include <masternode/node.h>
 #include <logging.h>
+#include <util/ranges.h>
 #include <spork.h>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#include <bls/bls_batchverifier.h>
#include <cxxtimer.hpp>
#include <llmq/commitment.h>
#include <llmq/quorums.h>
#include <llmq/signhash.h>
#include <llmq/signing.h>
#include <llmq/signing_shares.h>
#include <masternode/node.h>
#include <logging.h>
#include <spork.h>
#include <streams.h>
#include <util/thread.h>
#include <validationinterface.h>
#include <unordered_map>
using llmq::CSigSharesManager;
static bool PreVerifyRecoveredSig(Consensus::LLMQType& llmqType, const llmq::CQuorumManager& quorum_manager, const llmq::CRecoveredSig& recoveredSig)
{
#include <bls/bls_batchverifier.h>
#include <cxxtimer.hpp>
#include <llmq/commitment.h>
#include <llmq/quorums.h>
#include <llmq/signhash.h>
#include <llmq/signing.h>
#include <llmq/signing_shares.h>
#include <masternode/node.h>
#include <logging.h>
#include <util/ranges.h>
#include <spork.h>
#include <streams.h>
#include <util/thread.h>
#include <validationinterface.h>
#include <unordered_map>
using llmq::CSigSharesManager;
static bool PreVerifyRecoveredSig(Consensus::LLMQType& llmqType, const llmq::CQuorumManager& quorum_manager, const llmq::CRecoveredSig& recoveredSig)
{
🤖 Prompt for AI Agents
In src/net_signing.cpp around lines 7 to 26, the file uses the ranges::all_of
alias but does not include Dash's helper header; add #include "util/ranges.h" to
the include block (place it with the other util headers, e.g. after
<util/thread.h>) so ranges::all_of is declared and the file compiles cleanly.

@coderabbitai coderabbitai bot requested a review from kwvg November 3, 2025 09:33
@coderabbitai
Copy link

coderabbitai bot commented Nov 3, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR restructures node synchronization and network messaging infrastructure across five primary areas. First, it relocates masternode synchronization to the node layer (moving masternode/sync.h → node/sync.h) and renames associated constants from MASTERNODE_SYNC_* to NODE_SYNC_*. Second, it introduces a new NetHandler-based plugin architecture where peer message processing is delegated to pluggable handlers (NetGovernance, NetInstantSend, NetSigning) managed by a new PeerManagerInternal interface. Third, it refactors CGovernanceManager by removing the Schedule method, replacing RequestGovernanceObjectVotes with PrepareVotesToRequest, and updating governance object lookup patterns. Fourth, it substantially redesigns CInstantSendManager and CSigSharesManager by removing CQuorumManager and PeerManager dependencies respectively, shifting to NodeId-centric APIs and eliminating worker threads in favor of explicit synchronous processing. Fifth, it updates the build system and removes the legacy CMasternodeSync implementation, consolidating synchronization logic into the relocated node/sync.h header.

Sequence Diagram

sequenceDiagram
    actor App as Application<br/>Startup
    participant PM as PeerManager
    participant NH as NetHandler<br/>(Gov/IS/Signing)
    participant GM as CGovernanceManager
    participant ISM as CInstantSendManager
    participant SM as CSigningManager

    App->>PM: AddExtraHandler(NetGovernance)
    App->>PM: AddExtraHandler(NetInstantSend)
    App->>PM: AddExtraHandler(NetSigning)
    
    rect rgb(200, 220, 255)
        note over App,SM: Startup & Handler Lifecycle
        App->>PM: StartHandlers()
        PM->>NH: Start()
        Note over NH: Initialize worker threads<br/>(if applicable)
        
        App->>PM: ScheduleHandlers(scheduler)
        PM->>NH: Schedule(scheduler, connman)
        Note over NH: Register periodic tasks<br/>(e.g., governance tick)
    end

    rect rgb(200, 255, 220)
        note over App,SM: Message Processing Flow
        App->>PM: ProcessMessage(node, type, data)
        PM->>NH: ProcessMessage(node, type, data)
        alt Message Type Handled
            NH->>GM: PrepareVotesToRequest(...) or<br/>ProcessTick(...)
            NH->>ISM: ProcessInstantSendLock(...) returns variant
            NH->>SM: ProcessRecoveredSig(...) returns bool
        else Message Type Not Handled
            NH-->>PM: Return unhandled
        end
    end

    rect rgb(255, 240, 200)
        note over App,SM: Governance Sync Flow
        Note over NH: NetGovernance::ProcessTick()
        NH->>GM: PrepareVotesToRequest(nodes, asked_map, now, peers_max)
        activate GM
            Note over GM: Compute vote hashes to request<br/>respecting throttle state
            GM-->>NH: Return (hashes_to_request, hashes_remaining)
        deactivate GM
        NH->>PM: PeerRelayInv(vote_inv) for each peer
    end

    rect rgb(255, 220, 220)
        note over App,SM: Shutdown
        App->>PM: StopHandlers()
        PM->>NH: Stop()
        Note over NH: Stop worker threads,<br/>cleanup state
        
        App->>PM: RemoveHandlers()
        Note over PM: Clear handler list
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Areas requiring extra attention:

  • src/governance/governance.cpp & .h: Major refactoring of governance object lookup, vote collection, and message handling; PrepareVotesToRequest signature and semantics must be verified against all call sites
  • src/instantsend/instantsend.cpp & .h: Removal of CQuorumManager dependency, ProcessInstantSendLock return type change to std::variant, and elimination of WorkThreadMain; verify all async paths and pending lock handling
  • src/llmq/signing_shares.cpp & .h: AsyncSignIfMember signature change (removed signer parameter), NodeId-centric API redesign, and FetchPendingSigShares/SignPendingSigShare new methods; cross-check all signing call sites
  • src/llmq/signing.cpp & .h: CSigningManager constructor signature change (removed CChainState), ProcessRecoveredSig return type and behavior change, elimination of worker thread methods; verify integration with new handlers
  • src/net_processing.cpp & .h: Introduction of PeerManagerInternal abstraction, NetHandler plugin system, and new handler lifecycle methods; verify message dispatch logic and handler management correctness
  • src/net_governance.cpp & .h: New NetGovernance handler implementation for governance synchronization and vote request orchestration; validate governance tick logic and peer request rate-limiting
  • src/net_instantsend.cpp & .h, src/net_signing.cpp & .h: New handler implementations for IS and signing processing; verify message routing, batch verification, and thread lifecycle
  • src/node/sync.cpp & .h: CMasternodeSync moved from masternode/ with constant renaming; ensure all constant references updated and no stale dependencies remain
  • Makefile.am changes: Verify new source files are properly listed and build system reflects architectural reorganization
  • Header include changes: Confirm all MASTERNODE_SYNC_* → NODE_SYNC_* renames are complete and no orphaned masternode/sync.h includes remain

Possibly related PRs

  • dashpay/dash#6841: Modifies AsyncSignIfMember API signature and call sites across llmq signing infrastructure, directly aligning with the signing parameter removal in this PR
  • dashpay/dash#6820: Refactors message processing API with ProcessMessage signature changes, NodeId usage, and PeerManagerInternal abstraction foundation that this PR builds upon

Suggested reviewers

  • PastaPastaPasta
  • UdjinM6
  • kwvg

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "refactor: drop dependency on net_processing for multiple consensus related objects" accurately captures the primary change in this changeset. The title clearly communicates that the main focus is decoupling consensus-related components from network processing code, which is directly supported by the extensive refactoring across llmq, governance, coinjoin, instantsend, and chainlock modules throughout the codebase. The title is concise, specific enough for a teammate scanning history to understand the core objective, and avoids vague language or noise.
Description Check ✅ Passed The pull request description is comprehensive and directly relevant to the changeset. It explains the problem (tight coupling between network and consensus code), the proposed solution (NetHandler bridge interface), the technical approach with code example, and measurable outcomes (circular dependency reduction from 56 to 37). The description provides specific context about unlocking kernel backports and clearly states this is a proof-of-concept. The information is concrete and meaningful rather than generic or vague, making it clear how the described work relates to the actual code changes present in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

♻️ Duplicate comments (1)
src/net_processing.cpp (1)

598-601: About the commented-out destructor code

The comment-only destructor was previously flagged. Beyond style, it must actively call RemoveHandlers() to safely unregister validation callbacks. Please implement the destructor as in the earlier diff rather than leaving commented code.

🧹 Nitpick comments (8)
src/net_processing.cpp (5)

1092-1092: Guard access to m_handlers to avoid shutdown races

m_handlers is mutated in RemoveHandlers() and iterated in ProcessMessage() (Line 5448). Add a small mutex (or SharedMutex) around reads/writes to prevent iterator invalidation during shutdown.

Apply this minimal pattern:

-    std::vector<std::unique_ptr<NetHandler>> m_handlers;
+    mutable std::mutex m_handlers_mutex;
+    std::vector<std::unique_ptr<NetHandler>> m_handlers;

And take the lock in Add/Remove/Start/Stop/Interrupt/Schedule and in the ProcessMessage loop that iterates handlers. Example for iteration (see Line 5448):

-        for (const auto& handler : m_handlers) {
+        std::lock_guard<std::mutex> lk(m_handlers_mutex);
+        for (const auto& handler : m_handlers) {
             handler->ProcessMessage(pfrom, msg_type, vRecv);
         }

1674-1682: StopHandlers() order is good; add brief comment

You unregister before Stop(), which prevents callbacks during teardown. Consider a short comment documenting this ordering to avoid future regressions.


1684-1697: Schedule/Interrupt/Start: consider locking

Wrap loops over m_handlers with the proposed m_handlers_mutex to avoid concurrent modification during shutdown.


5448-5451: Handler dispatch placement and stream reuse

  • Dispatch is gated by “found” net message types above; this blocks handler processing of extension messages not listed in getAllNetMessageTypes(). Call handlers before the unknown-command fallback so plugins can handle new types.
  • vRecv is passed by reference to many subsystems and then to all handlers. If two handlers process the same msg_type, the first may consume vRecv, starving the next. If multiple handlers are expected to observe the same payload, pass a copy per handler or document exclusivity.

Option A (call handlers unconditionally, before unknown fallback):

-    if (found)
-    {
+    if (found) {
         ...
-        for (const auto& handler : m_handlers) {
-            handler->ProcessMessage(pfrom, msg_type, vRecv);
-        }
-        return;
-    }
+        {
+            std::lock_guard<std::mutex> lk(m_handlers_mutex);
+            for (const auto& handler : m_handlers) {
+                handler->ProcessMessage(pfrom, msg_type, vRecv);
+            }
+        }
+        return;
+    }
+    // Give handlers a chance to process unknown/extension messages
+    {
+        std::lock_guard<std::mutex> lk(m_handlers_mutex);
+        for (const auto& handler : m_handlers) {
+            handler->ProcessMessage(pfrom, msg_type, vRecv);
+        }
+    }
+    // Fallback if unhandled:

If multiple handlers must process the same payload, consider:

-            handler->ProcessMessage(pfrom, msg_type, vRecv);
+            CDataStream tmp = vRecv; // shallow copy of the stream buffer
+            handler->ProcessMessage(pfrom, msg_type, tmp);

Please confirm the intended handler model (single owner vs fanout). If fanout is intended, adopt the copy approach; if single-owner, document it to avoid future double-consumption bugs.


6526-6575: Preserve peer attribution in PeerPostProcessMessage

PeerPostProcessMessage() forwards with node = -1, so errors and erasures aren’t attributed to the source peer. Prefer passing the NodeId (or extend the interface to accept it) so Misbehaving/EraseObjectRequest can act on the correct peer.

Possible interface tweak:

-    void PeerPostProcessMessage(MessageProcessingResult&& ret) override;
+    void PeerPostProcessMessage(NodeId nodeid, MessageProcessingResult&& ret) override;

And

-    PostProcessMessage(std::move(ret), -1);
+    PostProcessMessage(std::move(ret), nodeid);
src/llmq/signing_shares.h (3)

442-464: Consider further refinement in final implementation.

The substantial expansion of the public API surface successfully decouples from PeerManager but creates extensive method exposure. The class shifts from an encapsulated manager with internal workflow to a collection of utilities orchestrated externally by NetSigning.

For the final implementation, consider:

  • Whether some of these methods could be grouped into smaller, focused interfaces
  • If the exposed internal state management creates fragile coupling through shared lock requirements
  • Whether helper classes could encapsulate related operations (e.g., node state management, sig share collection)

Given this is a proof-of-concept refactor, the current approach is reasonable for validating the architecture direction.


447-448: Consider direct dependency injection in final version.

These accessor methods expose internal dependencies through CSigSharesManager. For the final implementation, consider whether NetSigning should receive CActiveMasternodeManager and CSporkManager directly via dependency injection rather than accessing them through CSigSharesManager. This would reduce indirection and make dependencies more explicit.

For this proof-of-concept refactor, the current approach is acceptable.


389-484: Verify thread-safety coordination in final implementation.

The lock annotations are correctly specified, with EXCLUSIVE_LOCKS_REQUIRED(!cs) indicating methods that internally acquire locks. However, the expanded public API creates additional thread-safety coordination requirements between CSigSharesManager and NetSigning.

For the final implementation, ensure:

  • NetSigning doesn't introduce new locks that could create deadlock potential when calling into CSigSharesManager
  • The locking discipline is documented clearly for maintainers
  • Consider whether the recursive mutex is necessary or if simpler locking patterns could be achieved with the new architecture

The current proof-of-concept approach appears reasonable based on the provided context.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f7dad69 and f1b5240.

📒 Files selected for processing (55)
  • src/Makefile.am (4 hunks)
  • src/chainlock/chainlock.cpp (1 hunks)
  • src/chainlock/signing.cpp (2 hunks)
  • src/coinjoin/client.cpp (1 hunks)
  • src/coinjoin/coinjoin.cpp (1 hunks)
  • src/coinjoin/server.cpp (1 hunks)
  • src/dsnotificationinterface.cpp (1 hunks)
  • src/evo/mnauth.cpp (1 hunks)
  • src/governance/governance.cpp (15 hunks)
  • src/governance/governance.h (3 hunks)
  • src/governance/object.cpp (1 hunks)
  • src/governance/signing.cpp (1 hunks)
  • src/governance/vote.cpp (1 hunks)
  • src/init.cpp (7 hunks)
  • src/instantsend/instantsend.cpp (8 hunks)
  • src/instantsend/instantsend.h (5 hunks)
  • src/instantsend/signing.cpp (3 hunks)
  • src/llmq/context.cpp (1 hunks)
  • src/llmq/ehf_signals.cpp (2 hunks)
  • src/llmq/quorums.cpp (1 hunks)
  • src/llmq/signing.cpp (8 hunks)
  • src/llmq/signing.h (5 hunks)
  • src/llmq/signing_shares.cpp (25 hunks)
  • src/llmq/signing_shares.h (3 hunks)
  • src/masternode/active/context.cpp (1 hunks)
  • src/masternode/active/notificationinterface.cpp (0 hunks)
  • src/masternode/active/notificationinterface.h (0 hunks)
  • src/masternode/payments.cpp (1 hunks)
  • src/masternode/sync.cpp (0 hunks)
  • src/masternode/utils.cpp (1 hunks)
  • src/msg_result.h (0 hunks)
  • src/net.cpp (1 hunks)
  • src/net.h (1 hunks)
  • src/net_governance.cpp (1 hunks)
  • src/net_governance.h (1 hunks)
  • src/net_instantsend.cpp (1 hunks)
  • src/net_instantsend.h (1 hunks)
  • src/net_processing.cpp (7 hunks)
  • src/net_processing.h (2 hunks)
  • src/net_signing.cpp (1 hunks)
  • src/net_signing.h (1 hunks)
  • src/node/chainstate.cpp (2 hunks)
  • src/node/context.cpp (1 hunks)
  • src/node/interfaces.cpp (1 hunks)
  • src/node/sync.cpp (1 hunks)
  • src/node/sync.h (4 hunks)
  • src/rpc/governance.cpp (1 hunks)
  • src/rpc/mining.cpp (1 hunks)
  • src/rpc/node.cpp (1 hunks)
  • src/rpc/quorums.cpp (1 hunks)
  • src/test/util/net.h (1 hunks)
  • src/test/util/setup_common.cpp (3 hunks)
  • src/validation.h (0 hunks)
  • src/wallet/interfaces.cpp (1 hunks)
  • test/lint/lint-circular-dependencies.py (2 hunks)
💤 Files with no reviewable changes (5)
  • src/masternode/active/notificationinterface.h
  • src/validation.h
  • src/masternode/active/notificationinterface.cpp
  • src/msg_result.h
  • src/masternode/sync.cpp
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{cpp,h,cc,cxx,hpp}: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction

Files:

  • src/rpc/node.cpp
  • src/net.h
  • src/wallet/interfaces.cpp
  • src/rpc/governance.cpp
  • src/masternode/payments.cpp
  • src/coinjoin/server.cpp
  • src/coinjoin/coinjoin.cpp
  • src/governance/object.cpp
  • src/node/interfaces.cpp
  • src/dsnotificationinterface.cpp
  • src/masternode/active/context.cpp
  • src/test/util/setup_common.cpp
  • src/net_instantsend.h
  • src/rpc/mining.cpp
  • src/test/util/net.h
  • src/node/chainstate.cpp
  • src/llmq/quorums.cpp
  • src/net_signing.cpp
  • src/evo/mnauth.cpp
  • src/rpc/quorums.cpp
  • src/coinjoin/client.cpp
  • src/chainlock/chainlock.cpp
  • src/net_governance.cpp
  • src/net_signing.h
  • src/net.cpp
  • src/llmq/signing.cpp
  • src/chainlock/signing.cpp
  • src/llmq/context.cpp
  • src/masternode/utils.cpp
  • src/node/context.cpp
  • src/llmq/ehf_signals.cpp
  • src/governance/vote.cpp
  • src/node/sync.h
  • src/instantsend/instantsend.cpp
  • src/net_processing.h
  • src/node/sync.cpp
  • src/net_processing.cpp
  • src/governance/governance.cpp
  • src/net_instantsend.cpp
  • src/net_governance.h
  • src/llmq/signing_shares.cpp
  • src/llmq/signing.h
  • src/governance/signing.cpp
  • src/instantsend/signing.cpp
  • src/instantsend/instantsend.h
  • src/governance/governance.h
  • src/init.cpp
  • src/llmq/signing_shares.h
src/{masternode,evo}/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

Masternode lists must use immutable data structures (Immer library) for thread safety

Files:

  • src/masternode/payments.cpp
  • src/masternode/active/context.cpp
  • src/evo/mnauth.cpp
  • src/masternode/utils.cpp
src/{test,wallet/test,qt/test}/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests for C++ code should be placed in src/test/, src/wallet/test/, or src/qt/test/ and use Boost::Test or Qt 5 for GUI tests

Files:

  • src/test/util/setup_common.cpp
  • src/test/util/net.h
🧠 Learnings (19)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.
📚 Learning: 2025-07-20T18:42:49.794Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T18:42:49.794Z
Learning: Applies to src/{masternode,evo}/**/*.{cpp,h,cc,cxx,hpp} : Masternode lists must use immutable data structures (Immer library) for thread safety

Applied to files:

  • src/rpc/node.cpp
  • src/wallet/interfaces.cpp
  • src/rpc/governance.cpp
  • src/masternode/payments.cpp
  • src/coinjoin/server.cpp
  • src/coinjoin/coinjoin.cpp
  • src/governance/object.cpp
  • src/node/interfaces.cpp
  • src/test/util/setup_common.cpp
  • src/rpc/mining.cpp
  • src/llmq/quorums.cpp
  • src/evo/mnauth.cpp
  • src/coinjoin/client.cpp
  • src/chainlock/chainlock.cpp
  • src/net.cpp
  • src/chainlock/signing.cpp
  • src/masternode/utils.cpp
  • src/governance/vote.cpp
  • src/node/sync.h
  • src/instantsend/instantsend.cpp
  • src/Makefile.am
  • src/governance/signing.cpp
  • src/instantsend/signing.cpp
  • src/init.cpp
📚 Learning: 2025-10-02T18:29:54.756Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6840
File: src/net_processing.cpp:2882-2886
Timestamp: 2025-10-02T18:29:54.756Z
Learning: Across net_processing.cpp, once LLMQContext (m_llmq_ctx) is asserted non-null, its subcomponents (e.g., isman, qdkgsman, quorum_block_processor) are treated as initialized and used without extra null checks.

Applied to files:

  • src/net.h
  • src/masternode/active/context.cpp
  • src/test/util/setup_common.cpp
  • src/node/chainstate.cpp
  • src/net_signing.cpp
  • src/evo/mnauth.cpp
  • src/llmq/signing.cpp
  • src/llmq/context.cpp
  • src/net_processing.cpp
  • src/net_instantsend.cpp
  • src/llmq/signing_shares.cpp
  • src/llmq/signing.h
  • src/instantsend/instantsend.h
  • src/llmq/signing_shares.h
📚 Learning: 2025-07-20T18:42:49.794Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T18:42:49.794Z
Learning: Applies to src/evo/specialtx.h : Special transactions use payload extensions defined in src/evo/specialtx.h

Applied to files:

  • src/wallet/interfaces.cpp
  • src/coinjoin/client.cpp
  • src/llmq/ehf_signals.cpp
📚 Learning: 2025-10-02T18:29:54.756Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6840
File: src/net_processing.cpp:2882-2886
Timestamp: 2025-10-02T18:29:54.756Z
Learning: In src/net_processing.cpp, if ActiveContext (m_active_ctx) is non-null, its members (including cj_server) are guaranteed to be initialized; call sites can safely dereference m_active_ctx->cj_server without an additional null-check.

Applied to files:

  • src/masternode/active/context.cpp
  • src/net_processing.cpp
📚 Learning: 2025-01-02T21:50:00.967Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6504
File: src/llmq/context.cpp:42-43
Timestamp: 2025-01-02T21:50:00.967Z
Learning: LLMQContext manages concurrency for the `CInstantSendManager`. Previously, this was handled globally; now it's handled as a class member in `LLMQContext`, but the concurrency control remains consistent.

Applied to files:

  • src/masternode/active/context.cpp
  • src/net_instantsend.h
  • src/llmq/context.cpp
  • src/instantsend/instantsend.cpp
  • src/net_instantsend.cpp
  • src/instantsend/signing.cpp
  • src/instantsend/instantsend.h
  • src/llmq/signing_shares.h
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • src/test/util/setup_common.cpp
  • src/node/chainstate.cpp
📚 Learning: 2025-10-03T11:20:37.475Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6838
File: src/active/context.cpp:29-33
Timestamp: 2025-10-03T11:20:37.475Z
Learning: In Dash codebase, NodeContext (src/node/context.h) serves only as a container with trivial c/d-tors; member lifetime is explicitly managed via reset() calls in the shutdown sequence (src/init.cpp), not by declaration order. For example, active_ctx.reset() is called before DashChainstateSetupClose handles llmq_ctx teardown, ensuring proper destruction order regardless of declaration order in the struct.

Applied to files:

  • src/test/util/setup_common.cpp
  • src/node/context.cpp
  • src/init.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().

Applied to files:

  • src/net_instantsend.h
  • src/net_instantsend.cpp
📚 Learning: 2025-09-09T13:04:06.013Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/compat/compat.h:0-0
Timestamp: 2025-09-09T13:04:06.013Z
Learning: WSAEISCONN is only used within WIN32 conditional compilation blocks in the codebase, so it doesn't require errno mapping for non-Windows platforms in src/compat/compat.h.

Applied to files:

  • src/test/util/net.h
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/node/chainstate.cpp
📚 Learning: 2025-01-07T18:50:44.838Z
Learnt from: knst
Repo: dashpay/dash PR: 6511
File: src/evo/deterministicmns.cpp:1369-1373
Timestamp: 2025-01-07T18:50:44.838Z
Learning: The functions `MigrateDBIfNeeded` and `MigrateDBIfNeeded2` in `src/evo/deterministicmns.cpp` are temporary and will be removed in a future version. Refactoring suggestions for these functions should be avoided.

Applied to files:

  • src/llmq/quorums.cpp
  • src/governance/signing.cpp
📚 Learning: 2025-07-15T14:53:04.819Z
Learnt from: knst
Repo: dashpay/dash PR: 6691
File: src/test/llmq_params_tests.cpp:148-151
Timestamp: 2025-07-15T14:53:04.819Z
Learning: In the Dash Core LLMQ implementation, signingActiveQuorumCount is never 0 in the actual parameters defined in params.h, making division by zero scenarios unrealistic in the max_cycles() function.

Applied to files:

  • src/rpc/quorums.cpp
  • src/llmq/signing_shares.cpp
  • src/llmq/signing.h
📚 Learning: 2025-07-29T14:32:48.369Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.

Applied to files:

  • src/llmq/signing.cpp
  • src/chainlock/signing.cpp
  • src/llmq/signing.h
📚 Learning: 2024-12-29T17:43:41.755Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6504
File: src/llmq/quorums.cpp:224-224
Timestamp: 2024-12-29T17:43:41.755Z
Learning: The `CQuorumManager` is fully initialized by `LLMQContext`, addressing any concerns about the manager’s initialization sequence.

Applied to files:

  • src/llmq/context.cpp
  • src/llmq/signing_shares.h
📚 Learning: 2025-07-23T09:30:34.631Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.h:5-6
Timestamp: 2025-07-23T09:30:34.631Z
Learning: Dash Core uses BITCOIN_ prefix for header guards as the standard convention, inherited from Bitcoin Core. Only a few BLS-specific files in src/bls/ use DASH_ prefix. The vast majority of files (385+) use BITCOIN_ prefix.

Applied to files:

  • src/node/sync.h
📚 Learning: 2025-10-21T11:09:34.688Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6849
File: src/governance/governance.cpp:1339-1343
Timestamp: 2025-10-21T11:09:34.688Z
Learning: In PR #6849, `cmapVoteToObject` was intentionally moved from `GovernanceStore` to `CGovernanceManager` as a memory-only variable and is NOT guarded by `cs_store`. It relies on `CacheMap`'s internal thread-safety instead.

Applied to files:

  • src/governance/governance.cpp
📚 Learning: 2025-10-28T08:54:00.392Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6926
File: test/functional/feature_governance_cl.py:0-0
Timestamp: 2025-10-28T08:54:00.392Z
Learning: In Dash tests, the scheduler (mockscheduler) operates independently of network state. Isolated nodes should still run scheduler-based cleanup processes like governance cleanup, even if they have different state due to network isolation.

Applied to files:

  • src/governance/governance.cpp
  • src/init.cpp
📚 Learning: 2025-08-19T15:08:00.835Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/commitment.cpp:54-60
Timestamp: 2025-08-19T15:08:00.835Z
Learning: In Dash Core, llmq_params.size == 1 is used only for regtest environments, not on public networks, which significantly reduces the risk profile of code paths specific to single-member quorums.

Applied to files:

  • src/llmq/signing.h
🧬 Code graph analysis (18)
src/net_instantsend.h (3)
src/instantsend/instantsend.h (1)
  • instantsend (35-41)
src/net_processing.h (1)
  • PeerManagerInternal (58-72)
src/net_instantsend.cpp (12)
  • ProcessMessage (17-60)
  • ProcessMessage (17-17)
  • Start (62-75)
  • Start (62-62)
  • Stop (77-91)
  • Stop (77-77)
  • WorkThreadMain (241-265)
  • WorkThreadMain (241-241)
  • ProcessPendingISLocks (214-239)
  • ProcessPendingISLocks (214-214)
  • ProcessPendingInstantSendLocks (93-211)
  • ProcessPendingInstantSendLocks (93-95)
src/test/util/net.h (1)
src/net_processing.h (1)
  • PeerManager (105-105)
src/net_signing.cpp (5)
src/llmq/signing_shares.cpp (2)
  • CSigSharesManager (179-189)
  • CSigSharesManager (191-191)
src/llmq/signing.cpp (6)
  • IsQuorumActive (588-597)
  • IsQuorumActive (588-588)
  • ProcessRecoveredSig (361-381)
  • ProcessRecoveredSig (361-361)
  • ProcessRecoveredSig (455-494)
  • ProcessRecoveredSig (455-455)
src/net_processing.cpp (30)
  • id (701-701)
  • id (705-705)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • pfrom (617-617)
  • pfrom (638-639)
  • pfrom (751-753)
  • pfrom (762-762)
  • pfrom (770-770)
  • pfrom (773-773)
  • pfrom (775-775)
  • pfrom (777-777)
  • pfrom (873-873)
  • pfrom (1055-1055)
  • WITH_LOCK (331-334)
  • WITH_LOCK (3234-3234)
  • WITH_LOCK (3256-3256)
  • inv (631-631)
  • inv (632-632)
  • inv (655-655)
  • inv (656-656)
  • inv (657-657)
  • inv (669-669)
  • inv (675-675)
  • inv (963-963)
  • inv (2388-2388)
  • node_id (653-653)
  • node_id (748-748)
  • now (689-689)
  • now (1012-1013)
src/masternode/active/context.cpp (4)
  • Start (53-57)
  • Start (53-53)
  • Stop (59-63)
  • Stop (59-59)
src/net_signing.h (1)
  • Start (34-36)
src/net_governance.cpp (2)
src/net_processing.cpp (16)
  • inv (631-631)
  • inv (632-632)
  • inv (655-655)
  • inv (656-656)
  • inv (657-657)
  • inv (669-669)
  • inv (675-675)
  • inv (963-963)
  • inv (2388-2388)
  • pnode (637-637)
  • pnode (642-642)
  • pnode (652-652)
  • pnode (737-737)
  • pnode (781-781)
  • pnode (853-853)
  • pnode (855-855)
src/net.h (1)
  • FullyConnectedOnly (1291-1291)
src/net_signing.h (4)
src/llmq/signing_shares.h (1)
  • llmq (35-485)
src/llmq/signing.h (1)
  • CSigningManager (157-230)
src/net_processing.h (3)
  • NetHandler (74-90)
  • NetHandler (78-81)
  • PeerManagerInternal (58-72)
src/net_signing.cpp (22)
  • ProcessMessage (53-142)
  • ProcessMessage (53-53)
  • NotifyRecoveredSig (390-393)
  • NotifyRecoveredSig (390-390)
  • Start (144-154)
  • Start (144-144)
  • Stop (156-169)
  • Stop (156-156)
  • WorkThreadSigning (247-259)
  • WorkThreadSigning (247-247)
  • WorkThreadShares (355-388)
  • WorkThreadShares (355-355)
  • ProcessPendingSigShares (275-353)
  • ProcessPendingSigShares (275-275)
  • ProcessPendingRecoveredSigs (184-245)
  • ProcessPendingRecoveredSigs (184-184)
  • ProcessRecoveredSig (171-182)
  • ProcessRecoveredSig (171-171)
  • BanNode (41-51)
  • BanNode (41-41)
  • RemoveBannedNodeStates (261-271)
  • RemoveBannedNodeStates (261-261)
src/llmq/signing.cpp (2)
src/llmq/signing.h (1)
  • CSigningManager (157-230)
src/net_signing.cpp (2)
  • ProcessRecoveredSig (171-182)
  • ProcessRecoveredSig (171-171)
src/node/sync.h (2)
src/node/sync.cpp (18)
  • BumpAssetLastTime (41-46)
  • BumpAssetLastTime (41-41)
  • GetAssetName (48-57)
  • GetAssetName (48-48)
  • GetSyncStatus (87-95)
  • GetSyncStatus (87-87)
  • Reset (22-39)
  • Reset (22-22)
  • SwitchToNextAsset (59-85)
  • SwitchToNextAsset (59-59)
  • ProcessMessage (97-110)
  • ProcessMessage (97-97)
  • AcceptedBlockHeader (112-120)
  • AcceptedBlockHeader (112-112)
  • NotifyHeaderTip (122-135)
  • NotifyHeaderTip (122-122)
  • UpdatedBlockTip (137-174)
  • UpdatedBlockTip (137-137)
src/dsnotificationinterface.cpp (6)
  • AcceptedBlockHeader (46-50)
  • AcceptedBlockHeader (46-46)
  • NotifyHeaderTip (52-55)
  • NotifyHeaderTip (52-52)
  • UpdatedBlockTip (65-85)
  • UpdatedBlockTip (65-65)
src/instantsend/instantsend.cpp (2)
src/logging.h (1)
  • LogAcceptDebug (235-238)
src/node/interfaces.cpp (18)
  • hash (853-870)
  • hash (853-853)
  • hash (892-896)
  • hash (892-892)
  • hash (918-923)
  • hash (918-918)
  • tx (609-612)
  • tx (609-609)
  • tx (732-735)
  • tx (732-732)
  • tx (736-739)
  • tx (736-736)
  • tx (757-760)
  • tx (757-757)
  • tx (1002-1009)
  • tx (1002-1002)
  • tx (1021-1036)
  • tx (1021-1021)
src/net_processing.h (6)
src/net_processing.cpp (86)
  • PeerMisbehaving (6527-6530)
  • PeerMisbehaving (6527-6527)
  • pnode (637-637)
  • pnode (642-642)
  • pnode (652-652)
  • pnode (737-737)
  • pnode (781-781)
  • pnode (853-853)
  • pnode (855-855)
  • PeerIsBanned (6532-6535)
  • PeerIsBanned (6532-6532)
  • node_id (653-653)
  • node_id (748-748)
  • PeerEraseObjectRequest (6537-6540)
  • PeerEraseObjectRequest (6537-6537)
  • nodeid (627-627)
  • nodeid (630-630)
  • nodeid (643-643)
  • nodeid (654-654)
  • nodeid (660-660)
  • nodeid (677-677)
  • nodeid (679-679)
  • nodeid (717-718)
  • nodeid (728-728)
  • nodeid (860-860)
  • nodeid (862-862)
  • nodeid (1038-1038)
  • nodeid (1072-1072)
  • inv (631-631)
  • inv (632-632)
  • inv (655-655)
  • inv (656-656)
  • inv (657-657)
  • inv (669-669)
  • inv (675-675)
  • inv (963-963)
  • inv (2388-2388)
  • PeerRelayInv (6542-6545)
  • PeerRelayInv (6542-6542)
  • PeerRelayInvFiltered (6547-6550)
  • PeerRelayInvFiltered (6547-6547)
  • PeerRelayInvFiltered (6552-6555)
  • PeerRelayInvFiltered (6552-6552)
  • PeerRelayRecoveredSig (6572-6575)
  • PeerRelayRecoveredSig (6572-6572)
  • sig_hash (658-658)
  • PeerAskPeersForTransaction (6557-6560)
  • PeerAskPeersForTransaction (6557-6557)
  • txid (633-633)
  • txid (659-659)
  • txid (663-663)
  • txid (666-666)
  • PeerGetRequestedObjectCount (6562-6565)
  • PeerGetRequestedObjectCount (6562-6562)
  • PeerPostProcessMessage (6567-6570)
  • PeerPostProcessMessage (6567-6567)
  • ret (661-661)
  • ret (683-683)
  • scheduler (623-623)
  • scheduler (649-649)
  • scheduler (692-692)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • pfrom (617-617)
  • pfrom (638-639)
  • pfrom (751-753)
  • pfrom (762-762)
  • pfrom (770-770)
  • pfrom (773-773)
  • pfrom (775-775)
  • pfrom (777-777)
  • pfrom (873-873)
  • pfrom (1055-1055)
  • AddExtraHandler (1651-1658)
  • AddExtraHandler (1651-1651)
  • handler (644-644)
  • RemoveHandlers (1660-1665)
  • RemoveHandlers (1660-1660)
  • StartHandlers (1667-1672)
  • StartHandlers (1667-1667)
  • StopHandlers (1674-1682)
  • StopHandlers (1674-1674)
  • InterruptHandlers (1684-1689)
  • InterruptHandlers (1684-1684)
  • ScheduleHandlers (1691-1696)
  • ScheduleHandlers (1691-1691)
src/net_instantsend.cpp (7)
  • inv (186-186)
  • Stop (77-91)
  • Stop (77-77)
  • Start (62-75)
  • Start (62-62)
  • ProcessMessage (17-60)
  • ProcessMessage (17-17)
src/init.cpp (3)
  • Interrupt (230-256)
  • Interrupt (230-230)
  • handler (480-480)
src/net_signing.cpp (6)
  • Stop (156-169)
  • Stop (156-156)
  • Start (144-154)
  • Start (144-144)
  • ProcessMessage (53-142)
  • ProcessMessage (53-53)
src/net_signing.h (1)
  • Start (34-36)
src/net_governance.cpp (2)
  • Schedule (21-54)
  • Schedule (21-21)
src/node/sync.cpp (4)
src/net.h (1)
  • AllNodes (1297-1297)
src/net_processing.cpp (11)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • peer (697-697)
  • peer (832-832)
  • peer (937-937)
  • peer (938-938)
  • peer (1045-1045)
  • peer (1053-1053)
  • pindexNew (608-608)
  • UpdatedBlockTip (2192-2227)
  • UpdatedBlockTip (2192-2192)
src/governance/governance.cpp (4)
  • ProcessMessage (183-325)
  • ProcessMessage (183-184)
  • UpdatedBlockTip (1229-1251)
  • UpdatedBlockTip (1229-1229)
src/dsnotificationinterface.cpp (6)
  • AcceptedBlockHeader (46-50)
  • AcceptedBlockHeader (46-46)
  • NotifyHeaderTip (52-55)
  • NotifyHeaderTip (52-52)
  • UpdatedBlockTip (65-85)
  • UpdatedBlockTip (65-65)
src/net_processing.cpp (2)
src/validationinterface.cpp (4)
  • RegisterValidationInterface (133-138)
  • RegisterValidationInterface (133-133)
  • UnregisterValidationInterface (145-150)
  • UnregisterValidationInterface (145-145)
src/llmq/dkgsessionhandler.cpp (2)
  • Misbehaving (112-116)
  • Misbehaving (112-112)
src/net_instantsend.cpp (2)
src/net_processing.cpp (24)
  • ProcessMessage (3669-5458)
  • ProcessMessage (3669-3674)
  • pfrom (617-617)
  • pfrom (638-639)
  • pfrom (751-753)
  • pfrom (762-762)
  • pfrom (770-770)
  • pfrom (773-773)
  • pfrom (775-775)
  • pfrom (777-777)
  • pfrom (873-873)
  • pfrom (1055-1055)
  • hash (1026-1026)
  • hash (1032-1032)
  • WITH_LOCK (331-334)
  • WITH_LOCK (3234-3234)
  • WITH_LOCK (3256-3256)
  • id (701-701)
  • id (705-705)
  • LOCK (323-329)
  • LOCK (336-340)
  • LOCK (341-345)
  • ret (661-661)
  • ret (683-683)
src/net_instantsend.h (1)
  • Start (32-34)
src/net_governance.h (4)
src/governance/governance.cpp (2)
  • CGovernanceManager (70-86)
  • CGovernanceManager (88-92)
src/node/sync.cpp (1)
  • CMasternodeSync (14-20)
src/net_processing.h (3)
  • NetHandler (74-90)
  • NetHandler (78-81)
  • PeerManagerInternal (58-72)
src/net_governance.cpp (8)
  • Schedule (21-54)
  • Schedule (21-21)
  • ProcessTick (143-323)
  • ProcessTick (143-143)
  • SendGovernanceSyncRequest (56-61)
  • SendGovernanceSyncRequest (56-56)
  • RequestGovernanceObjectVotes (63-141)
  • RequestGovernanceObjectVotes (63-63)
src/llmq/signing_shares.cpp (3)
src/net_processing.cpp (14)
  • node_id (653-653)
  • node_id (748-748)
  • LOCK (323-329)
  • LOCK (336-340)
  • LOCK (341-345)
  • id (701-701)
  • id (705-705)
  • pnode (637-637)
  • pnode (642-642)
  • pnode (652-652)
  • pnode (737-737)
  • pnode (781-781)
  • pnode (853-853)
  • pnode (855-855)
src/spork.h (1)
  • cs (226-339)
src/llmq/signing.cpp (2)
  • IsQuorumActive (588-597)
  • IsQuorumActive (588-588)
src/llmq/signing.h (4)
src/llmq/signhash.h (3)
  • llmq (17-52)
  • SignHash (24-46)
  • hash (64-73)
src/llmq/signhash.cpp (1)
  • SignHash (14-22)
src/llmq/signing.cpp (17)
  • CSigningManager (328-332)
  • AlreadyHave (334-347)
  • AlreadyHave (334-334)
  • GetRecoveredSigForGetData (349-359)
  • GetRecoveredSigForGetData (349-349)
  • ProcessRecoveredSig (361-381)
  • ProcessRecoveredSig (361-361)
  • ProcessRecoveredSig (455-494)
  • ProcessRecoveredSig (455-455)
  • FetchPendingReconstructed (447-452)
  • FetchPendingReconstructed (447-447)
  • CollectPendingRecoveredSigsToVerify (383-445)
  • CollectPendingRecoveredSigsToVerify (383-386)
  • GetListeners (496-500)
  • GetListeners (496-496)
  • Cleanup (513-526)
  • Cleanup (513-513)
src/net_signing.cpp (2)
  • ProcessRecoveredSig (171-182)
  • ProcessRecoveredSig (171-171)
src/instantsend/instantsend.h (4)
src/net_instantsend.h (1)
  • instantsend (12-16)
src/instantsend/lock.h (1)
  • instantsend (18-41)
src/instantsend/instantsend.cpp (14)
  • CInstantSendManager (51-62)
  • CInstantSendManager (64-64)
  • GetCycleBlockHeight (71-78)
  • GetCycleBlockHeight (71-71)
  • IsKnownInstantSend (80-87)
  • IsKnownInstantSend (80-80)
  • EnqueueInstantSendLock (89-110)
  • EnqueueInstantSendLock (89-89)
  • PrepareTxToRetry (391-407)
  • PrepareTxToRetry (391-391)
  • GetPendingLocks (112-143)
  • GetPendingLocks (112-112)
  • ProcessInstantSendLock (145-219)
  • ProcessInstantSendLock (145-146)
src/llmq/signing.cpp (1)
  • CSigningManager (328-332)
src/governance/governance.h (2)
src/governance/governance.cpp (14)
  • PrepareVotesToRequest (1056-1096)
  • PrepareVotesToRequest (1056-1056)
  • RequestOrphanObjects (1253-1278)
  • RequestOrphanObjects (1253-1253)
  • CleanOrphanObjects (1280-1296)
  • CleanOrphanObjects (1280-1280)
  • CheckAndRemove (415-534)
  • CheckAndRemove (415-415)
  • GetMNManager (536-539)
  • GetMNManager (536-536)
  • FetchRelayInventory (541-547)
  • FetchRelayInventory (541-541)
  • RequestGovernanceObject (1020-1049)
  • RequestGovernanceObject (1020-1020)
src/protocol.h (1)
  • CInv (531-568)
src/llmq/signing_shares.h (3)
src/llmq/signing_shares.cpp (40)
  • CSigSharesManager (179-189)
  • CSigSharesManager (191-191)
  • CreateSigShare (1348-1416)
  • CreateSigShare (1348-1348)
  • ForceReAnnouncement (1419-1443)
  • ForceReAnnouncement (1419-1419)
  • HandleNewRecoveredSig (1445-1450)
  • HandleNewRecoveredSig (1445-1445)
  • AsyncSignIfMember (642-722)
  • AsyncSignIfMember (642-644)
  • FetchPendingSigShares (1319-1324)
  • FetchPendingSigShares (1319-1319)
  • SignPendingSigShare (1326-1346)
  • SignPendingSigShare (1326-1326)
  • SendMessages (973-1000)
  • SendMessages (973-973)
  • Cleanup (1133-1253)
  • Cleanup (1133-1133)
  • MarkAsBanned (1299-1317)
  • MarkAsBanned (1299-1299)
  • RemoveAsBanned (1282-1297)
  • RemoveAsBanned (1282-1282)
  • GetAllNodes (1270-1280)
  • GetAllNodes (1270-1270)
  • ProcessMessageSigShare (334-379)
  • ProcessMessageSigShare (334-334)
  • ProcessSigShare (495-546)
  • ProcessSigShare (495-495)
  • ProcessMessageSigSesAnn (203-233)
  • ProcessMessageSigSesAnn (203-203)
  • ProcessMessageSigShares (235-278)
  • ProcessMessageSigShares (235-235)
  • ProcessMessageBatchedSigShares (280-332)
  • ProcessMessageBatchedSigShares (280-280)
  • CollectPendingSigSharesToVerify (423-492)
  • CollectPendingSigSharesToVerify (423-425)
  • PreVerifyBatchedSigShares (381-421)
  • PreVerifyBatchedSigShares (381-382)
  • TryRecoverSig (548-625)
  • TryRecoverSig (548-548)
src/net_signing.cpp (2)
  • ProcessMessage (53-142)
  • ProcessMessage (53-53)
src/llmq/signhash.h (1)
  • llmq (17-52)
🪛 GitHub Actions: Check Merge Fast-Forward Only
src/governance/governance.cpp

[error] 1-1: Merge conflict in src/governance/governance.cpp during automatic merge.

src/governance/governance.h

[error] 1-1: Merge conflict in src/governance/governance.h during automatic merge.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
🔇 Additional comments (43)
src/net.h (1)

38-38: Verify that llmq/params.h provides all necessary symbols previously available from consensus/params.h.

This single-line include swap is part of the broader decoupling refactor. Since this is an architectural change affecting the dependency graph, ensure the substituted header exports all type definitions and macros that net.h and its consumers depend on.

If you see build failures mentioning undefined references or missing type definitions (e.g., Consensus:: types), this change may need adjustment or additional includes to bridge the transition.

test/lint/lint-circular-dependencies.py (3)

31-31: New circular dependency introduced in refactoring.

This circular dependency chain doesn't involve net_processing, which aligns with the PR's goal of decoupling network code from consensus components. As a proof-of-concept, this appears acceptable.


55-55: Acceptable circular dependency from sync relocation.

This simple circular dependency reflects the relocation of synchronization logic from masternode/sync.h to node/sync.h. The bidirectional dependency between net and node/sync is expected and architecturally sound for synchronization infrastructure.


32-32: Verify this circular dependency chain against the PR baseline before merging.

I was unable to fully verify the original concern due to environment constraints, but I can confirm that line 32 contains a notably long 7-component circular dependency chain with net_processing. In the current state, there are 4 circular dependencies involving net_processing (lines 32, 33, 34, and 52), with line 32 being the longest by far.

Before accepting this PR, please manually verify:

  1. What was the baseline count on the develop branch? (The PR claims to reduce from 56 to 37 net_processing-related circular dependencies)
  2. Were there longer chains on develop that have since been broken, making line 32 an acceptable remainder?
  3. Is the 7-component chain the shortest achievable given current module architecture?
src/masternode/active/context.cpp (4)

29-30: I need to directly examine the codebase to verify the architectural claims made in the review comment.

Based on the verification performed, I can see that CSigSharesManager still retains ProcessMessage methods for handling sig shares network messages. However, I couldn't fully verify the specific architectural changes regarding the peerman parameter removal and worker thread lifecycle changes due to search limitations. Since the original review comment makes specific architectural claims that require precise confirmation of the constructor signature and thread management changes, and given that the proof-of-concept nature of this PR involves intentional architectural shifts, I'll generate a rewritten review that reflects what can be confirmed and flags what needs verification.

Verify CSigSharesManager architecture properly integrates with net_processing layer after peerman dependency removal.

The removal of the peerman parameter from CSigSharesManager's constructor and the elimination of worker thread management from Start/Stop methods represent significant architectural changes. While CSigSharesManager retains ProcessMessage* methods for handling sig shares messages, confirm that:

  • Messages are properly routed from net_processing to CSigSharesManager without direct peer manager access
  • Thread safety is maintained for message processing without explicit worker thread lifecycle management
  • The NetHandler bridge pattern properly replaces the removed peer manager dependencies

59-63: No changes needed - resource cleanup architecture is correct.

The removal of explicit worker thread stopping is appropriate because CSigSharesManager has a default destructor and shareman is managed as a unique_ptr in ActiveContext. Worker threads belong to NetSigning (the NetHandler), not to CSigSharesManager itself. The call to UnregisterAsRecoveredSigsListener() correctly prevents new callbacks before destruction, and the unique_ptr ensures automatic cleanup. The threading lifecycle is properly managed at the NetSigning layer, not at the ActiveContext layer.


49-51: The empty Interrupt() method is intentional and correct.

ActiveContext manages lifecycle through Start/Stop methods only. Start() initiates qdkgsman threads and listener registration; Stop() unregisters listeners and stops threads. No managed entity (shareman, gov_signer, cj_server, ehf_sighandler) exposes an Interrupt() method. LLMQContext follows the identical pattern with an empty Interrupt(). The architecture does not use thread-based async operations requiring separate interruption signals—thread management is handled directly in Start/Stop, and listener lifecycle through registration/unregistration.

The review comment's assumptions about NetHandler-based processing and worker thread removal in shareman do not match the actual implementation.

Likely an incorrect or invalid review comment.


53-57: NetHandler properly replaces shareman worker thread lifecycle—verified correct.

The architectural refactoring is sound. Worker threads are now managed by NetSigning (a NetHandler subclass) rather than shareman directly. Initialization sequence (init.cpp:2283–2285) ensures threads start via peerman->StartHandlers() before active_ctx->Start() registers the listener. Thread safety is maintained with existing RecursiveMutex and Mutex guards. Null checks protect non-masternode scenarios.

src/node/context.cpp (1)

23-23: Include swap LGTM

node/sync.h import here is consistent with the refactor; no functional impact in this TU.

src/coinjoin/coinjoin.cpp (2)

19-19: Include swap LGTM

Switching to node/sync.h aligns with the decoupling goal.


57-61: No API mismatch; review comment is incorrect

The header declaration (src/coinjoin/coinjoin.h:215) provides a default argument: bool IsTimeOutOfBounds(int64_t current_time = GetAdjustedTime()) const;

All call sites—including those in coinjoin.cpp:139, coinjoin.cpp:155, server.cpp:161, and client.cpp:94—invoke the method without arguments and will compile successfully using the default GetAdjustedTime(). The implementation in coinjoin.cpp:57 correctly omits repeating the default argument (standard C++ practice).

Likely an incorrect or invalid review comment.

src/evo/mnauth.cpp (1)

13-13: Include swap LGTM

node/sync.h provides CMasternodeSync used here; no behavior change.

Please confirm node/sync.h exports the same PROTECTED API surface required by CMNAuth::ProcessMessage to keep linkage stable.

src/masternode/payments.cpp (1)

15-15: Include swap LGTM

No functional change; payments logic unaffected.

src/governance/vote.cpp (1)

10-10: Include swap LGTM

Governance voting compiles against node/sync.h; no behavior change expected.

src/coinjoin/server.cpp (1)

11-11: Include swap LGTM

Server side uses CMasternodeSync; node/sync.h import is consistent across the refactor.

src/net.cpp (1)

44-44: Refactor verified - stale includes removed

Verification confirms the refactor is complete. The old <masternode/sync.h> include has been fully removed from the codebase, and <node/sync.h> correctly provides CMasternodeSync. The change to src/net.cpp is properly aligned with the refactor.

src/masternode/utils.cpp (1)

13-13: Review comment is incorrect—symbols are properly exported from their respective headers

The review comment incorrectly assumes PROBE_WAIT_INTERVAL is exported by node/sync.h. In reality, PROBE_WAIT_INTERVAL is defined in net.h (line 73), which the file already includes directly (line 7). The #include <node/sync.h> is for CMasternodeSync, which is properly exported from that header. The code correctly accesses both symbols from their appropriate sources with no missing includes or risk of silent behavior drift.

Likely an incorrect or invalid review comment.

src/governance/signing.cpp (1)

10-10: LGTM: Header relocation is consistent with the PR's architectural changes.

The migration from masternode/sync.h to node/sync.h aligns with the broader refactor to consolidate synchronization logic at the node level.

src/chainlock/chainlock.cpp (1)

21-21: LGTM: Consistent header migration.

src/coinjoin/client.cpp (1)

13-13: LGTM: Header relocation follows the established pattern.

src/governance/object.cpp (1)

12-12: LGTM: Header change is consistent.

src/chainlock/signing.cpp (2)

13-13: LGTM: Header relocation is consistent.


144-144: AsyncSignIfMember refactoring verified as complete.

All call sites in the codebase have been successfully updated to use the new signature without the m_sigman parameter:

  • 5 call sites confirmed across: src/rpc/quorums.cpp, src/llmq/ehf_signals.cpp, src/instantsend/signing.cpp (2 calls), and src/chainlock/signing.cpp
  • CSigSharesManager properly manages signing through its CSigningManager& sigman member variable rather than accepting it as a parameter
  • No remaining calls with the old signature pattern were found

The decoupling is complete and correctly implemented.

src/test/util/setup_common.cpp (2)

20-20: LGTM: Header additions prepare for future net handler integration.

The new includes for masternode/active/context.h, net_instantsend.h, and net_signing.h align with the introduction of NetHandler components mentioned in the PR objectives.

Also applies to: 23-24, 70-70


370-375: Note: Commented-out net handler integration.

The commented code indicates future integration of NetInstantSend, NetSigning, and NetGovernance handlers in the test setup. The TODO comment suggests uncertainty about whether these handlers are needed in regression tests.

This is appropriate for a proof-of-concept PR that will be split into smaller, focused changes.

src/llmq/ehf_signals.cpp (2)

81-81: AsyncSignIfMember signature updated with additional parameters.

The call includes quorumHash and boolean flags not present in the chainlock/signing.cpp call site. This suggests different overloads or a more complete signature for EHF signing.


114-127: LGTM: HandleNewRecoveredSig refactored to early-return pattern.

The refactoring is functionally equivalent:

  • Success: immediately return MessageProcessingResult with transaction hash
  • Failure: immediately return empty result after logging
  • No match: fall through to return empty result

The tighter lock scope around ProcessTransaction is a good practice.

src/Makefile.am (2)

298-300: LGTM: Build configuration updated to include new net handler headers.

The addition of net_governance.h, net_instantsend.h, net_signing.h, and node/sync.h properly registers the new components introduced in this refactor.

Also applies to: 318-318


562-564: LGTM: Source files correctly added to the node library.

The new net handler implementations and relocated sync source are properly included in libbitcoin_node_a_SOURCES.

Also applies to: 577-577

src/instantsend/instantsend.h (6)

8-10: LGTM!

The added includes are appropriate for the header's dependencies on InstantSend-specific types and base classes.


22-23: LGTM!

The <variant> include is needed for ProcessInstantSendLock's return type, and <vector> is used by PrepareTxToRetry.


40-40: LGTM!

The updated PendingState structure appropriately tracks pending InstantSend locks with their source peer, supporting the new NetInstantSend integration.


100-100: LGTM!

The Signer() accessor appropriately exposes the internal signer for NetInstantSend integration. Callers correctly handle the nullable pointer, as seen in the ProcessInstantSendLock implementation.


125-138: Well-designed interface for NetInstantSend integration.

The new public helpers appropriately expose the minimal interface needed for network layer communication while maintaining proper encapsulation. The methods include appropriate lock annotations (except for the issue flagged separately), and the use of std::variant for ProcessInstantSendLock's return type clearly communicates the three possible outcomes (unknown/ignored, transaction found, transaction not found).


87-89: Constructor signature changes verified and correctly implemented.

All call sites have been updated. The only instantiation of CInstantSendManager at src/llmq/context.cpp:35-36 correctly passes all parameters matching the new signature. The mn_sync parameter is properly const at the call site, and parameter name differences (unit_tests vs unitTests, wipe vs fWipe) are inconsequential—the types align correctly.

src/net_processing.cpp (3)

60-60: LGTM: include updates

Using llmq/signhash.h and node/sync.h here is appropriate given the new PlatformBan verification and sync header move.

Also applies to: 64-64


644-650: Handler management API addition looks good

The Add/Remove/Start/Stop/Interrupt/Schedule surface aligns with the bridge intent.

Please confirm these are invoked from init/shutdown in the intended order (Add → Start/Schedule; Interrupt → Stop → Remove) for all build configs.


651-662: PeerManagerInternal wrappers are fine

Thin wrappers correctly delegate to existing internals.

src/llmq/signing_shares.h (5)

360-366: LGTM! Well-designed data transfer object.

The PendingSignatureData struct appropriately encapsulates the parameters needed for deferred signature share creation. The const members prevent accidental modification, and the constructor properly moves the shared_ptr quorum for efficiency.


369-372: Helpful markers for future refactoring.

These TODO comments appropriately document the architectural direction, acknowledging that the current refactoring is an intermediate step toward further decoupling. This aligns well with the PR's proof-of-concept nature and helps reviewers understand the intended evolution.


467-468: Excellent refactoring to static method.

Converting PreVerifyBatchedSigShares to a static method with explicit parameters is good practice. This makes dependencies explicit, enables easier testing, and demonstrates that the method doesn't require instance state.


444-444: Appropriate use of [[nodiscard]].

The [[nodiscard]] attribute on SignPendingSigShare correctly ensures callers check whether signature recovery succeeded. Since the method may return nullptr on failure, ignoring the return value would lose critical information about the operation's success.


417-419: Successfully removes PeerManager dependency.

The updated constructor signature successfully eliminates the PeerManager dependency, which is a primary goal of this refactoring. The remaining dependencies are appropriate for the class's functionality and support the new NetSigning delegation pattern.


[[nodiscard]] MessageProcessingResult ProcessMessage(NodeId from, std::string_view msg_type, CDataStream& vRecv)
/* Helpers for communications between CInstantSendManager & NetInstantSend */
// GetCycleBlockHeight returns negative number if cycle_hash is now known
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo in comment.

The comment says "if cycle_hash is now known" but should say "if cycle_hash is not known" (based on the method returning a negative number to indicate unknown hash).

Apply this diff:

-    // GetCycleBlockHeight returns negative number if cycle_hash is now known
+    // GetCycleBlockHeight returns negative number if cycle_hash is not known
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// GetCycleBlockHeight returns negative number if cycle_hash is now known
// GetCycleBlockHeight returns negative number if cycle_hash is not known
🤖 Prompt for AI Agents
In src/instantsend/instantsend.h at line 126 the comment reads
"GetCycleBlockHeight returns negative number if cycle_hash is now known" —
change the typo "now" to "not" so it reads "GetCycleBlockHeight returns negative
number if cycle_hash is not known".

bool IsKnownInstantSend(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks);
void EnqueueInstantSendLock(NodeId from, const uint256& hash, const std::shared_ptr<instantsend::InstantSendLock>& islock)
EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks);
std::vector<CTransactionRef> PrepareTxToRetry() EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, cs_pendingRetry);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix incorrect lock annotation.

The annotation states cs_pendingRetry must already be held, but the implementation uses LOCK2(cs_nonLocked, cs_pendingRetry), which acquires both locks. This inconsistency can mislead about thread safety guarantees and lock ordering.

Apply this diff:

-    std::vector<CTransactionRef> PrepareTxToRetry() EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, cs_pendingRetry);
+    std::vector<CTransactionRef> PrepareTxToRetry() EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::vector<CTransactionRef> PrepareTxToRetry() EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, cs_pendingRetry);
std::vector<CTransactionRef> PrepareTxToRetry() EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
🤖 Prompt for AI Agents
In src/instantsend/instantsend.h around line 131, the lock annotation is
incorrect (it currently reads EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked,
cs_pendingRetry) while the implementation acquires both locks with
LOCK2(cs_nonLocked, cs_pendingRetry)); remove the stray '!' and update the
annotation to require both locks (e.g., EXCLUSIVE_LOCKS_REQUIRED(cs_nonLocked,
cs_pendingRetry)) so the declaration matches the implementation and correctly
documents the required exclusive locks.

Comment on lines +1272 to 1278
vector<NodeId> nodes;

LOCK(cs);
for (auto it = nodeStates.begin(); it != nodeStates.end();) {
if (m_peerman.IsBanned(it->first)) {
// re-request sigshares from other nodes
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
// using here template ForEach makes impossible to use lock annotation
it->second.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) NO_THREAD_SAFETY_ANALYSIS {
AssertLockHeld(cs);
sigSharesRequested.Erase(k);
});
it = nodeStates.erase(it);
} else {
++it;
}
nodes.reserve(nodeStates.size());
for (const auto& [node_id, _] : nodeStates) {
nodes.push_back(node_id);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix missing namespace on vector.
vector<NodeId> lacks the std:: qualifier, which breaks compilation. Please qualify it so it builds again.

-    vector<NodeId> nodes;
+    std::vector<NodeId> nodes;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
vector<NodeId> nodes;
LOCK(cs);
for (auto it = nodeStates.begin(); it != nodeStates.end();) {
if (m_peerman.IsBanned(it->first)) {
// re-request sigshares from other nodes
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
// using here template ForEach makes impossible to use lock annotation
it->second.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) NO_THREAD_SAFETY_ANALYSIS {
AssertLockHeld(cs);
sigSharesRequested.Erase(k);
});
it = nodeStates.erase(it);
} else {
++it;
}
nodes.reserve(nodeStates.size());
for (const auto& [node_id, _] : nodeStates) {
nodes.push_back(node_id);
}
std::vector<NodeId> nodes;
LOCK(cs);
nodes.reserve(nodeStates.size());
for (const auto& [node_id, _] : nodeStates) {
nodes.push_back(node_id);
}
🤖 Prompt for AI Agents
In src/llmq/signing_shares.cpp around lines 1272 to 1278, the declaration uses
unqualified vector<NodeId> which causes a compilation error; change it to
std::vector<NodeId> and ensure <vector> is included or already present in the
file, then rebuild to confirm the missing namespace is resolved.

Comment on lines +496 to 500
std::vector<CRecoveredSigsListener*> CSigningManager::GetListeners() const
{
LOCK(cs_listeners);
return recoveredSigsListeners;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard recovered-sig listeners against post-unregister use

GetListeners() now hands out raw CRecoveredSigsListener* without holding cs_listeners while they’re consumed. In the new flow (NetSigning::ProcessRecoveredSig), we copy the vector and release the mutex before iterating, so a concurrent UnregisterRecoveredSigsListener() (e.g. during shutdown) can erase the entry and destroy the object while another thread still dereferences the stale pointer. That’s a latent use-after-free that didn’t exist when callbacks were invoked under the lock. Please keep the listeners’ lifetime protected—either continue invoking callbacks while cs_listeners is held, or promote the stored handles to something that keeps the target alive (e.g. shared_ptr/weak_ptr). As written this is a critical concurrency regression.

Comment on lines +25 to +54
scheduler.scheduleEvery(
[this, &connman]() -> void {
if (ShutdownRequested()) return;
ProcessTick(connman);
},
std::chrono::seconds{1});

scheduler.scheduleEvery(
[this, &connman]() -> void {
if (!m_node_sync.IsSynced()) return;

// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
m_gov_manager.CleanOrphanObjects();
m_gov_manager.RequestOrphanObjects(connman);

// CHECK AND REMOVE - REPROCESS GOVERNANCE OBJECTS
m_gov_manager.CheckAndRemove();
},
std::chrono::minutes{5});

scheduler.scheduleEvery(
[this]() -> void {
auto relay_invs = m_gov_manager.FetchRelayInventory();
for (const auto& inv : relay_invs) {
m_peer_manager->PeerRelayInv(inv);
}
},
// Tests need tighter timings to avoid timeouts, use more relaxed pacing otherwise
Params().IsMockableChain() ? std::chrono::seconds{1} : std::chrono::seconds{5});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Cancel scheduled governance callbacks before destruction.

PeerManagerImpl::RemoveHandlers() clears m_handlers while the scheduler thread keeps running. The three scheduleEvery lambdas here capture this, so after the handler is erased the scheduler continues to invoke them with a dangling pointer, leading to use-after-free crashes during shutdown (and in any future hot-handler reload). We need to keep the returned FunctionHandles and cancel them from an overridden Stop() prior to destruction (and teach the header about the new members).

@@
-    scheduler.scheduleEvery(
+    m_tick_handle = scheduler.scheduleEvery(
@@
-    scheduler.scheduleEvery(
+    m_maintenance_handle = scheduler.scheduleEvery(
@@
-    scheduler.scheduleEvery(
+    m_relay_handle = scheduler.scheduleEvery(
         [this]() -> void {
             auto relay_invs = m_gov_manager.FetchRelayInventory();
             for (const auto& inv : relay_invs) {
                 m_peer_manager->PeerRelayInv(inv);
             }
         },
         Params().IsMockableChain() ? std::chrono::seconds{1} : std::chrono::seconds{5});
 }
+
+void NetGovernance::Stop()
+{
+    m_tick_handle.reset();
+    m_maintenance_handle.reset();
+    m_relay_handle.reset();
+}

(Declare the three CScheduler::FunctionHandle members and override Stop() in net_governance.h accordingly.)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/net_governance.cpp around lines 25-54, the three scheduler.scheduleEvery
lambdas capture this and can run after handlers are removed, causing
use-after-free; store the CScheduler::FunctionHandle returned from each
scheduleEvery into three new member variables declared in net_governance.h,
override Stop() in the class to call cancel() (or the scheduler's equivalent) on
those FunctionHandles before handler removal/destruction, and update the header
to add the three FunctionHandle members plus the Stop() override so the
scheduled callbacks are cancelled prior to destruction.

Comment on lines +8 to +47
#include <net_processing.h>

#include <util/threadinterrupt.h>

namespace instantsend
{
struct InstantSendLock;
using InstantSendLockPtr = std::shared_ptr<InstantSendLock>;
} // namespace instantsend
namespace llmq {
class CInstantSendManager;
class CQuorumManager;
} // namespace llmq

class NetInstantSend final : public NetHandler
{
public:
NetInstantSend(PeerManagerInternal* peer_manager, llmq::CInstantSendManager& is_manager, llmq::CQuorumManager& qman)
: NetHandler(peer_manager), m_is_manager{is_manager}, m_qman(qman)
{
workInterrupt.reset();
}
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) override;

void Start() override;
void Stop() override;
void Interrupt() override { workInterrupt(); };

void WorkThreadMain();
private:
void ProcessPendingISLocks(Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>>&& locks_to_process);

Uint256HashSet ProcessPendingInstantSendLocks(const Consensus::LLMQParams& llmq_params, int signOffset, bool ban,
const Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>>& pend);
// EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
llmq::CInstantSendManager& m_is_manager;
llmq::CQuorumManager& m_qman;

std::thread workThread;
CThreadInterrupt workInterrupt;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Include <thread> before declaring std::thread

This header declares std::thread workThread but never includes <thread>, so any TU that includes net_instantsend.h before pulling in <thread> will fail to compile. Please add the missing include.

 #include <net_processing.h>
 
 #include <util/threadinterrupt.h>
+
+#include <thread>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#include <net_processing.h>
#include <util/threadinterrupt.h>
namespace instantsend
{
struct InstantSendLock;
using InstantSendLockPtr = std::shared_ptr<InstantSendLock>;
} // namespace instantsend
namespace llmq {
class CInstantSendManager;
class CQuorumManager;
} // namespace llmq
class NetInstantSend final : public NetHandler
{
public:
NetInstantSend(PeerManagerInternal* peer_manager, llmq::CInstantSendManager& is_manager, llmq::CQuorumManager& qman)
: NetHandler(peer_manager), m_is_manager{is_manager}, m_qman(qman)
{
workInterrupt.reset();
}
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) override;
void Start() override;
void Stop() override;
void Interrupt() override { workInterrupt(); };
void WorkThreadMain();
private:
void ProcessPendingISLocks(Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>>&& locks_to_process);
Uint256HashSet ProcessPendingInstantSendLocks(const Consensus::LLMQParams& llmq_params, int signOffset, bool ban,
const Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>>& pend);
// EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
llmq::CInstantSendManager& m_is_manager;
llmq::CQuorumManager& m_qman;
std::thread workThread;
CThreadInterrupt workInterrupt;
#include <net_processing.h>
#include <util/threadinterrupt.h>
#include <thread>
namespace instantsend
{
struct InstantSendLock;
using InstantSendLockPtr = std::shared_ptr<InstantSendLock>;
} // namespace instantsend
namespace llmq {
class CInstantSendManager;
class CQuorumManager;
} // namespace llmq
class NetInstantSend final : public NetHandler
{
public:
NetInstantSend(PeerManagerInternal* peer_manager, llmq::CInstantSendManager& is_manager, llmq::CQuorumManager& qman)
: NetHandler(peer_manager), m_is_manager{is_manager}, m_qman(qman)
{
workInterrupt.reset();
}
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) override;
void Start() override;
void Stop() override;
void Interrupt() override { workInterrupt(); };
void WorkThreadMain();
private:
void ProcessPendingISLocks(Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>>&& locks_to_process);
Uint256HashSet ProcessPendingInstantSendLocks(const Consensus::LLMQParams& llmq_params, int signOffset, bool ban,
const Uint256HashMap<std::pair<NodeId, instantsend::InstantSendLockPtr>>& pend);
// EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
llmq::CInstantSendManager& m_is_manager;
llmq::CQuorumManager& m_qman;
std::thread workThread;
CThreadInterrupt workInterrupt;
🤖 Prompt for AI Agents
In src/net_instantsend.h around lines 8 to 47, the header declares std::thread
workThread but does not include <thread>, which can cause compilation failures
when this header is included before <thread>; add #include <thread> near the
other includes (e.g., after <util/threadinterrupt.h>) so std::thread is defined
before its use.

Comment on lines +598 to +601
~PeerManagerImpl() {
// probably do some disassignment
// m_handlers.clear();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix lifecycle: unregister validation callbacks and clear handlers in destructor

Handlers registered as CValidationInterface via AddExtraHandler() must be unregistered before destruction to avoid dangling pointers in g_signals. Currently the destructor does nothing; base NetHandler dtor calling Interrupt/Stop is insufficient because UnregisterValidationInterface(i) is done in StopHandlers(), not in the handler. Call RemoveHandlers() here.

Apply this diff:

-    ~PeerManagerImpl() {
-        // probably do some disassignment
-//        m_handlers.clear();
-    }
+    ~PeerManagerImpl() override {
+        // Ensure handlers are interrupted, stopped (which unregisters validation
+        // callbacks), and destroyed before PeerManagerImpl goes away.
+        RemoveHandlers();
+    }

Reference: RegisterValidationInterface/UnregisterValidationInterface is managed by the caller, not the callee (see src/validationinterface.cpp). Based on learnings.

🤖 Prompt for AI Agents
In src/net_processing.cpp around lines 598-601, the PeerManagerImpl destructor
currently does nothing; update it to call RemoveHandlers() so that any
CValidationInterface handlers registered via AddExtraHandler() are unregistered
and m_handlers are cleared before destruction. Ensure RemoveHandlers() is
invoked from the destructor path (and only once) to unregister validation
callbacks and clear handler state to avoid dangling pointers in g_signals.

Comment on lines +1651 to +1672
void PeerManagerImpl::AddExtraHandler(std::unique_ptr<NetHandler>&& handler)
{
assert(handler != nullptr);
if (auto i = dynamic_cast<CValidationInterface*>(handler.get()); i != nullptr) {
RegisterValidationInterface(i);
}
m_handlers.emplace_back(std::move(handler));
}

void PeerManagerImpl::RemoveHandlers()
{
InterruptHandlers();
StopHandlers();
m_handlers.clear();
}

void PeerManagerImpl::StartHandlers()
{
for (auto& handler : m_handlers) {
handler->Start();
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Balance validation interface registration with guaranteed unregistration

AddExtraHandler() registers CValidationInterface if present; StopHandlers() unregisters it. This is correct, but only if StopHandlers() is always called before destruction. Ensure the destructor fix (calling RemoveHandlers()) lands; otherwise g_signals will retain a dangling pointer.

Linking to the destructor comment above.

🤖 Prompt for AI Agents
In src/net_processing.cpp around lines 1651 to 1672, AddExtraHandler registers a
CValidationInterface from a handler but RemoveHandlers only stops/clears
handlers; ensure registration is balanced by guaranteeing unregistration: either
modify the PeerManagerImpl destructor to call RemoveHandlers() (so
StopHandlers/Unregister happens before destruction) or update RemoveHandlers()
to iterate m_handlers and call UnregisterValidationInterface for any
CValidationInterface before clearing; implement one of these fixes so g_signals
does not retain dangling pointers.

Comment on lines +63 to +68
if (!Params().GetLLMQ(llmqType).has_value()) {
m_peer_manager->PeerMisbehaving(pfrom.GetId(), 100);
}
if (PreVerifyRecoveredSig(llmqType, m_sig_manager.Qman(), *recoveredSig)) {
m_sig_manager.ProcessRecoveredSig(pfrom.GetId(), std::move(recoveredSig));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Return immediately after flagging an invalid LLMQ type

Once we know llmqType isn’t configured, we call PeerMisbehaving but continue into PreVerifyRecoveredSig. That path ends up in CQuorumManager::GetQuorum, which asserts that the type is valid. As written, a malicious peer can send a bogus llmqType, trigger the assert, and take down the node. Please bail out right after flagging the misbehavior:

         auto llmqType = recoveredSig->getLlmqType();
         if (!Params().GetLLMQ(llmqType).has_value()) {
             m_peer_manager->PeerMisbehaving(pfrom.GetId(), 100);
-        }
-        if (PreVerifyRecoveredSig(llmqType, m_sig_manager.Qman(), *recoveredSig)) {
+            return;
+        }
+        if (PreVerifyRecoveredSig(llmqType, m_sig_manager.Qman(), *recoveredSig)) {
             m_sig_manager.ProcessRecoveredSig(pfrom.GetId(), std::move(recoveredSig));
         }
🤖 Prompt for AI Agents
In src/net_signing.cpp around lines 63 to 68, after detecting that
Params().GetLLMQ(llmqType) has no value and calling
m_peer_manager->PeerMisbehaving(pfrom.GetId(), 100), stop further processing of
this message immediately (do not fall through into PreVerifyRecoveredSig). Fix
by bailing out right after flagging the misbehavior — return from the handler
(or otherwise skip/continue to the next message) so that PreVerifyRecoveredSig
and subsequent calls into CQuorumManager are not executed with an invalid
llmqType.

Comment on lines +9 to +56
#include <net_processing.h>
#include <validationinterface.h>
#include <util/threadinterrupt.h>

#include <memory>

namespace llmq {
class CSigSharesManager;
class CSigningManager;
} // namespace llmq
class NetSigning final : public NetHandler, public CValidationInterface
{
public:
NetSigning(PeerManagerInternal* peer_manager, llmq::CSigningManager& sig_manager, llmq::CSigSharesManager* shares_manager)
: NetHandler(peer_manager), m_sig_manager(sig_manager), m_shares_manager(shares_manager)
{
workInterrupt.reset();
}
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) override;

protected:
// CValidationInterface
void NotifyRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& sig) override;

// NetSigning
void Start() override;
void Stop() override;
void Interrupt() override { workInterrupt(); };

void WorkThreadSigning();
void WorkThreadShares();

private:
bool ProcessPendingSigShares();
bool ProcessPendingRecoveredSigs();
void ProcessRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& recoveredSig);
void BanNode(NodeId id);
void RemoveBannedNodeStates();

private:
llmq::CSigningManager& m_sig_manager;
llmq::CSigSharesManager* m_shares_manager;

std::thread signing_thread;
std::thread shares_thread;

CThreadInterrupt workInterrupt;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add <thread> include for std::thread members

NetSigning defines std::thread signing_thread/shares_thread but the header does not include <thread>, leading to compile errors when this file is included first in a TU. Please include <thread> alongside the other standard headers.

 #include <net_processing.h>
 #include <validationinterface.h>
 #include <util/threadinterrupt.h>
 
 #include <memory>
+#include <thread>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#include <net_processing.h>
#include <validationinterface.h>
#include <util/threadinterrupt.h>
#include <memory>
namespace llmq {
class CSigSharesManager;
class CSigningManager;
} // namespace llmq
class NetSigning final : public NetHandler, public CValidationInterface
{
public:
NetSigning(PeerManagerInternal* peer_manager, llmq::CSigningManager& sig_manager, llmq::CSigSharesManager* shares_manager)
: NetHandler(peer_manager), m_sig_manager(sig_manager), m_shares_manager(shares_manager)
{
workInterrupt.reset();
}
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) override;
protected:
// CValidationInterface
void NotifyRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& sig) override;
// NetSigning
void Start() override;
void Stop() override;
void Interrupt() override { workInterrupt(); };
void WorkThreadSigning();
void WorkThreadShares();
private:
bool ProcessPendingSigShares();
bool ProcessPendingRecoveredSigs();
void ProcessRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& recoveredSig);
void BanNode(NodeId id);
void RemoveBannedNodeStates();
private:
llmq::CSigningManager& m_sig_manager;
llmq::CSigSharesManager* m_shares_manager;
std::thread signing_thread;
std::thread shares_thread;
CThreadInterrupt workInterrupt;
};
#include <net_processing.h>
#include <validationinterface.h>
#include <util/threadinterrupt.h>
#include <memory>
#include <thread>
namespace llmq {
class CSigSharesManager;
class CSigningManager;
} // namespace llmq
class NetSigning final : public NetHandler, public CValidationInterface
{
public:
NetSigning(PeerManagerInternal* peer_manager, llmq::CSigningManager& sig_manager, llmq::CSigSharesManager* shares_manager)
: NetHandler(peer_manager), m_sig_manager(sig_manager), m_shares_manager(shares_manager)
{
workInterrupt.reset();
}
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv) override;
protected:
// CValidationInterface
void NotifyRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& sig) override;
// NetSigning
void Start() override;
void Stop() override;
void Interrupt() override { workInterrupt(); };
void WorkThreadSigning();
void WorkThreadShares();
private:
bool ProcessPendingSigShares();
bool ProcessPendingRecoveredSigs();
void ProcessRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig>& recoveredSig);
void BanNode(NodeId id);
void RemoveBannedNodeStates();
private:
llmq::CSigningManager& m_sig_manager;
llmq::CSigSharesManager* m_shares_manager;
std::thread signing_thread;
std::thread shares_thread;
CThreadInterrupt workInterrupt;
};
🤖 Prompt for AI Agents
In src/net_signing.h around lines 9 to 56, the header declares std::thread
members (signing_thread, shares_thread) but does not include the <thread>
header; add a #include <thread> alongside the other standard includes (e.g.,
with <memory>) so the std::thread type is available when this header is the
first inclusion unit, then rebuild to verify the missing include error is
resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant